10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * Author: Tatu Ylonen <ylo@cs.hut.fi>
30Sstevel@tonic-gate  * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
40Sstevel@tonic-gate  *                    All rights reserved
50Sstevel@tonic-gate  * This file contains code implementing the packet protocol and communication
60Sstevel@tonic-gate  * with the other side.  This same code is used both on client and server side.
70Sstevel@tonic-gate  *
80Sstevel@tonic-gate  * As far as I am concerned, the code I have written for this software
90Sstevel@tonic-gate  * can be used freely for any purpose.  Any derived versions of this
100Sstevel@tonic-gate  * software must be clearly marked as such, and if the derived work is
110Sstevel@tonic-gate  * incompatible with the protocol description in the RFC file, it must be
120Sstevel@tonic-gate  * called by a name other than "ssh" or "Secure Shell".
130Sstevel@tonic-gate  *
140Sstevel@tonic-gate  *
150Sstevel@tonic-gate  * SSH2 packet format added by Markus Friedl.
160Sstevel@tonic-gate  * Copyright (c) 2000, 2001 Markus Friedl.  All rights reserved.
170Sstevel@tonic-gate  *
180Sstevel@tonic-gate  * Redistribution and use in source and binary forms, with or without
190Sstevel@tonic-gate  * modification, are permitted provided that the following conditions
200Sstevel@tonic-gate  * are met:
210Sstevel@tonic-gate  * 1. Redistributions of source code must retain the above copyright
220Sstevel@tonic-gate  *    notice, this list of conditions and the following disclaimer.
230Sstevel@tonic-gate  * 2. Redistributions in binary form must reproduce the above copyright
240Sstevel@tonic-gate  *    notice, this list of conditions and the following disclaimer in the
250Sstevel@tonic-gate  *    documentation and/or other materials provided with the distribution.
260Sstevel@tonic-gate  *
270Sstevel@tonic-gate  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
280Sstevel@tonic-gate  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
290Sstevel@tonic-gate  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
300Sstevel@tonic-gate  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
310Sstevel@tonic-gate  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
320Sstevel@tonic-gate  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
330Sstevel@tonic-gate  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
340Sstevel@tonic-gate  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
350Sstevel@tonic-gate  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
360Sstevel@tonic-gate  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
370Sstevel@tonic-gate  */
380Sstevel@tonic-gate /*
39*5562Sjp161948  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
400Sstevel@tonic-gate  * Use is subject to license terms.
410Sstevel@tonic-gate  */
420Sstevel@tonic-gate 
43*5562Sjp161948 /* $OpenBSD: packet.c,v 1.148 2007/06/07 19:37:34 pvalchev Exp $ */
440Sstevel@tonic-gate 
450Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
460Sstevel@tonic-gate 
47*5562Sjp161948 #include "includes.h"
48*5562Sjp161948 
49*5562Sjp161948 #include "sys-queue.h"
500Sstevel@tonic-gate #include "xmalloc.h"
510Sstevel@tonic-gate #include "buffer.h"
520Sstevel@tonic-gate #include "packet.h"
530Sstevel@tonic-gate #include "bufaux.h"
540Sstevel@tonic-gate #include "crc32.h"
550Sstevel@tonic-gate #include "getput.h"
560Sstevel@tonic-gate #include "compress.h"
570Sstevel@tonic-gate #include "deattack.h"
580Sstevel@tonic-gate #include "channels.h"
590Sstevel@tonic-gate #include "compat.h"
600Sstevel@tonic-gate #include "ssh1.h"
610Sstevel@tonic-gate #include "ssh2.h"
620Sstevel@tonic-gate #include "cipher.h"
630Sstevel@tonic-gate #include "kex.h"
640Sstevel@tonic-gate #include "mac.h"
650Sstevel@tonic-gate #include "log.h"
660Sstevel@tonic-gate #include "canohost.h"
670Sstevel@tonic-gate #include "misc.h"
680Sstevel@tonic-gate #include "ssh.h"
690Sstevel@tonic-gate 
700Sstevel@tonic-gate #ifdef ALTPRIVSEP
710Sstevel@tonic-gate static int packet_server = 0;
720Sstevel@tonic-gate static int packet_monitor = 0;
730Sstevel@tonic-gate #endif /* ALTPRIVSEP */
740Sstevel@tonic-gate 
750Sstevel@tonic-gate #ifdef PACKET_DEBUG
760Sstevel@tonic-gate #define DBG(x) x
770Sstevel@tonic-gate #else
780Sstevel@tonic-gate #define DBG(x)
790Sstevel@tonic-gate #endif
800Sstevel@tonic-gate 
810Sstevel@tonic-gate /*
820Sstevel@tonic-gate  * This variable contains the file descriptors used for communicating with
830Sstevel@tonic-gate  * the other side.  connection_in is used for reading; connection_out for
840Sstevel@tonic-gate  * writing.  These can be the same descriptor, in which case it is assumed to
850Sstevel@tonic-gate  * be a socket.
860Sstevel@tonic-gate  */
870Sstevel@tonic-gate static int connection_in = -1;
880Sstevel@tonic-gate static int connection_out = -1;
890Sstevel@tonic-gate 
900Sstevel@tonic-gate /* Protocol flags for the remote side. */
910Sstevel@tonic-gate static u_int remote_protocol_flags = 0;
920Sstevel@tonic-gate 
930Sstevel@tonic-gate /* Encryption context for receiving data.  This is only used for decryption. */
940Sstevel@tonic-gate static CipherContext receive_context;
950Sstevel@tonic-gate 
960Sstevel@tonic-gate /* Encryption context for sending data.  This is only used for encryption. */
970Sstevel@tonic-gate static CipherContext send_context;
980Sstevel@tonic-gate 
990Sstevel@tonic-gate /* Buffer for raw input data from the socket. */
1000Sstevel@tonic-gate Buffer input;
1010Sstevel@tonic-gate 
1020Sstevel@tonic-gate /* Buffer for raw output data going to the socket. */
1030Sstevel@tonic-gate Buffer output;
1040Sstevel@tonic-gate 
1050Sstevel@tonic-gate /* Buffer for the partial outgoing packet being constructed. */
1060Sstevel@tonic-gate static Buffer outgoing_packet;
1070Sstevel@tonic-gate 
1080Sstevel@tonic-gate /* Buffer for the incoming packet currently being processed. */
1090Sstevel@tonic-gate static Buffer incoming_packet;
1100Sstevel@tonic-gate 
1110Sstevel@tonic-gate /* Scratch buffer for packet compression/decompression. */
1120Sstevel@tonic-gate static Buffer compression_buffer;
1130Sstevel@tonic-gate static int compression_buffer_ready = 0;
1140Sstevel@tonic-gate 
1150Sstevel@tonic-gate /* Flag indicating whether packet compression/decompression is enabled. */
1160Sstevel@tonic-gate static int packet_compression = 0;
1170Sstevel@tonic-gate 
1180Sstevel@tonic-gate /* default maximum packet size */
1190Sstevel@tonic-gate int max_packet_size = 32768;
1200Sstevel@tonic-gate 
1210Sstevel@tonic-gate /* Flag indicating whether this module has been initialized. */
1220Sstevel@tonic-gate static int initialized = 0;
1230Sstevel@tonic-gate 
1240Sstevel@tonic-gate /* Set to true if the connection is interactive. */
1250Sstevel@tonic-gate static int interactive_mode = 0;
1260Sstevel@tonic-gate 
1270Sstevel@tonic-gate /* Session key information for Encryption and MAC */
1280Sstevel@tonic-gate Newkeys *newkeys[MODE_MAX];
129*5562Sjp161948 static struct packet_state {
130*5562Sjp161948 	u_int32_t seqnr;
131*5562Sjp161948 	u_int32_t packets;
132*5562Sjp161948 	u_int64_t blocks;
133*5562Sjp161948 } p_read, p_send;
134*5562Sjp161948 
135*5562Sjp161948 static u_int64_t max_blocks_in, max_blocks_out;
136*5562Sjp161948 static u_int32_t rekey_limit;
1370Sstevel@tonic-gate 
1380Sstevel@tonic-gate /* Session key for protocol v1 */
1390Sstevel@tonic-gate static u_char ssh1_key[SSH_SESSION_KEY_LENGTH];
1400Sstevel@tonic-gate static u_int ssh1_keylen;
1410Sstevel@tonic-gate 
1420Sstevel@tonic-gate /* roundup current message to extra_pad bytes */
1430Sstevel@tonic-gate static u_char extra_pad = 0;
1440Sstevel@tonic-gate 
145*5562Sjp161948 struct packet {
146*5562Sjp161948 	TAILQ_ENTRY(packet) next;
147*5562Sjp161948 	u_char type;
148*5562Sjp161948 	Buffer payload;
149*5562Sjp161948 };
150*5562Sjp161948 TAILQ_HEAD(, packet) outgoing;
151*5562Sjp161948 
1520Sstevel@tonic-gate /*
1530Sstevel@tonic-gate  * Sets the descriptors used for communication.  Disables encryption until
1540Sstevel@tonic-gate  * packet_set_encryption_key is called.
1550Sstevel@tonic-gate  */
1560Sstevel@tonic-gate void
1570Sstevel@tonic-gate packet_set_connection(int fd_in, int fd_out)
1580Sstevel@tonic-gate {
1590Sstevel@tonic-gate 	Cipher *none = cipher_by_name("none");
1600Sstevel@tonic-gate 
1610Sstevel@tonic-gate 	if (none == NULL)
1620Sstevel@tonic-gate 		fatal("packet_set_connection: cannot load cipher 'none'");
1630Sstevel@tonic-gate 	connection_in = fd_in;
1640Sstevel@tonic-gate 	connection_out = fd_out;
1650Sstevel@tonic-gate 	cipher_init(&send_context, none, (unsigned char *) "", 0, NULL, 0, CIPHER_ENCRYPT);
1660Sstevel@tonic-gate 	cipher_init(&receive_context, none, (unsigned char *) "", 0, NULL, 0, CIPHER_DECRYPT);
1670Sstevel@tonic-gate 	newkeys[MODE_IN] = newkeys[MODE_OUT] = NULL;
1680Sstevel@tonic-gate 	if (!initialized) {
1690Sstevel@tonic-gate 		initialized = 1;
1700Sstevel@tonic-gate 		buffer_init(&input);
1710Sstevel@tonic-gate 		buffer_init(&output);
1720Sstevel@tonic-gate 		buffer_init(&outgoing_packet);
1730Sstevel@tonic-gate 		buffer_init(&incoming_packet);
174*5562Sjp161948 		TAILQ_INIT(&outgoing);
1750Sstevel@tonic-gate 	} else {
1760Sstevel@tonic-gate 		buffer_clear(&input);
1770Sstevel@tonic-gate 		buffer_clear(&output);
1780Sstevel@tonic-gate 		buffer_clear(&outgoing_packet);
1790Sstevel@tonic-gate 		buffer_clear(&incoming_packet);
1800Sstevel@tonic-gate 	}
1810Sstevel@tonic-gate 
1820Sstevel@tonic-gate 	/*
1830Sstevel@tonic-gate 	 * Prime the cache for get_remote_ipaddr() while we have a
1840Sstevel@tonic-gate 	 * socket on which to do a getpeername().
1850Sstevel@tonic-gate 	 */
1860Sstevel@tonic-gate 	(void) get_remote_ipaddr();
1870Sstevel@tonic-gate 
1880Sstevel@tonic-gate 	/* Kludge: arrange the close function to be called from fatal(). */
1890Sstevel@tonic-gate 	fatal_add_cleanup((void (*) (void *)) packet_close, NULL);
1900Sstevel@tonic-gate }
1910Sstevel@tonic-gate 
1920Sstevel@tonic-gate /* Returns 1 if remote host is connected via socket, 0 if not. */
1930Sstevel@tonic-gate 
1940Sstevel@tonic-gate int
1950Sstevel@tonic-gate packet_connection_is_on_socket(void)
1960Sstevel@tonic-gate {
1970Sstevel@tonic-gate 	struct sockaddr_storage from, to;
1980Sstevel@tonic-gate 	socklen_t fromlen, tolen;
1990Sstevel@tonic-gate 
2000Sstevel@tonic-gate 	/* filedescriptors in and out are the same, so it's a socket */
2010Sstevel@tonic-gate 	if (connection_in != -1 && connection_in == connection_out)
2020Sstevel@tonic-gate 		return 1;
2030Sstevel@tonic-gate 	fromlen = sizeof(from);
2040Sstevel@tonic-gate 	memset(&from, 0, sizeof(from));
2050Sstevel@tonic-gate 	if (getpeername(connection_in, (struct sockaddr *)&from, &fromlen) < 0)
2060Sstevel@tonic-gate 		return 0;
2070Sstevel@tonic-gate 	tolen = sizeof(to);
2080Sstevel@tonic-gate 	memset(&to, 0, sizeof(to));
2090Sstevel@tonic-gate 	if (getpeername(connection_out, (struct sockaddr *)&to, &tolen) < 0)
2100Sstevel@tonic-gate 		return 0;
2110Sstevel@tonic-gate 	if (fromlen != tolen || memcmp(&from, &to, fromlen) != 0)
2120Sstevel@tonic-gate 		return 0;
2130Sstevel@tonic-gate 	if (from.ss_family != AF_INET && from.ss_family != AF_INET6)
2140Sstevel@tonic-gate 		return 0;
2150Sstevel@tonic-gate 	return 1;
2160Sstevel@tonic-gate }
2170Sstevel@tonic-gate 
2180Sstevel@tonic-gate /* returns 1 if connection is via ipv4 */
2190Sstevel@tonic-gate 
2200Sstevel@tonic-gate int
2210Sstevel@tonic-gate packet_connection_is_ipv4(void)
2220Sstevel@tonic-gate {
2230Sstevel@tonic-gate 	struct sockaddr_storage to;
2240Sstevel@tonic-gate 	socklen_t tolen = sizeof(to);
2250Sstevel@tonic-gate 
2260Sstevel@tonic-gate 	memset(&to, 0, sizeof(to));
2270Sstevel@tonic-gate 	if (getsockname(connection_out, (struct sockaddr *)&to, &tolen) < 0)
2280Sstevel@tonic-gate 		return 0;
2290Sstevel@tonic-gate 	if (to.ss_family == AF_INET)
2300Sstevel@tonic-gate 		return 1;
2310Sstevel@tonic-gate #ifdef IPV4_IN_IPV6
2320Sstevel@tonic-gate 	if (to.ss_family == AF_INET6 &&
2330Sstevel@tonic-gate 	    IN6_IS_ADDR_V4MAPPED(&((struct sockaddr_in6 *)&to)->sin6_addr))
2340Sstevel@tonic-gate 		return 1;
2350Sstevel@tonic-gate #endif
2360Sstevel@tonic-gate 	return 0;
2370Sstevel@tonic-gate }
2380Sstevel@tonic-gate 
2390Sstevel@tonic-gate /* Sets the connection into non-blocking mode. */
2400Sstevel@tonic-gate 
2410Sstevel@tonic-gate void
2420Sstevel@tonic-gate packet_set_nonblocking(void)
2430Sstevel@tonic-gate {
2440Sstevel@tonic-gate 	/* Set the socket into non-blocking mode. */
2450Sstevel@tonic-gate 	if (fcntl(connection_in, F_SETFL, O_NONBLOCK) < 0)
2460Sstevel@tonic-gate 		error("fcntl O_NONBLOCK: %.100s", strerror(errno));
2470Sstevel@tonic-gate 
2480Sstevel@tonic-gate 	if (connection_out != connection_in) {
2490Sstevel@tonic-gate 		if (fcntl(connection_out, F_SETFL, O_NONBLOCK) < 0)
2500Sstevel@tonic-gate 			error("fcntl O_NONBLOCK: %.100s", strerror(errno));
2510Sstevel@tonic-gate 	}
2520Sstevel@tonic-gate }
2530Sstevel@tonic-gate 
2540Sstevel@tonic-gate /* Returns the socket used for reading. */
2550Sstevel@tonic-gate 
2560Sstevel@tonic-gate int
2570Sstevel@tonic-gate packet_get_connection_in(void)
2580Sstevel@tonic-gate {
2590Sstevel@tonic-gate 	return connection_in;
2600Sstevel@tonic-gate }
2610Sstevel@tonic-gate 
2620Sstevel@tonic-gate /* Returns the descriptor used for writing. */
2630Sstevel@tonic-gate 
2640Sstevel@tonic-gate int
2650Sstevel@tonic-gate packet_get_connection_out(void)
2660Sstevel@tonic-gate {
2670Sstevel@tonic-gate 	return connection_out;
2680Sstevel@tonic-gate }
2690Sstevel@tonic-gate 
2700Sstevel@tonic-gate /* Closes the connection and clears and frees internal data structures. */
2710Sstevel@tonic-gate 
2720Sstevel@tonic-gate void
2730Sstevel@tonic-gate packet_close(void)
2740Sstevel@tonic-gate {
2750Sstevel@tonic-gate 	if (!initialized)
2760Sstevel@tonic-gate 		return;
2770Sstevel@tonic-gate 	initialized = 0;
2780Sstevel@tonic-gate 	if (connection_in == connection_out) {
2790Sstevel@tonic-gate 		shutdown(connection_out, SHUT_RDWR);
2800Sstevel@tonic-gate 		close(connection_out);
2810Sstevel@tonic-gate 	} else {
2820Sstevel@tonic-gate 		close(connection_in);
2830Sstevel@tonic-gate 		close(connection_out);
2840Sstevel@tonic-gate 	}
2850Sstevel@tonic-gate 	buffer_free(&input);
2860Sstevel@tonic-gate 	buffer_free(&output);
2870Sstevel@tonic-gate 	buffer_free(&outgoing_packet);
2880Sstevel@tonic-gate 	buffer_free(&incoming_packet);
2890Sstevel@tonic-gate 	if (compression_buffer_ready) {
2900Sstevel@tonic-gate 		buffer_free(&compression_buffer);
2910Sstevel@tonic-gate 		buffer_compress_uninit();
2920Sstevel@tonic-gate 		compression_buffer_ready = 0;
2930Sstevel@tonic-gate 	}
2940Sstevel@tonic-gate 	cipher_cleanup(&send_context);
2950Sstevel@tonic-gate 	cipher_cleanup(&receive_context);
2960Sstevel@tonic-gate }
2970Sstevel@tonic-gate 
2980Sstevel@tonic-gate /* Sets remote side protocol flags. */
2990Sstevel@tonic-gate 
3000Sstevel@tonic-gate void
3010Sstevel@tonic-gate packet_set_protocol_flags(u_int protocol_flags)
3020Sstevel@tonic-gate {
3030Sstevel@tonic-gate 	remote_protocol_flags = protocol_flags;
3040Sstevel@tonic-gate }
3050Sstevel@tonic-gate 
3060Sstevel@tonic-gate /* Returns the remote protocol flags set earlier by the above function. */
3070Sstevel@tonic-gate 
3080Sstevel@tonic-gate u_int
3090Sstevel@tonic-gate packet_get_protocol_flags(void)
3100Sstevel@tonic-gate {
3110Sstevel@tonic-gate 	return remote_protocol_flags;
3120Sstevel@tonic-gate }
3130Sstevel@tonic-gate 
3140Sstevel@tonic-gate /*
3150Sstevel@tonic-gate  * Starts packet compression from the next packet on in both directions.
3160Sstevel@tonic-gate  * Level is compression level 1 (fastest) - 9 (slow, best) as in gzip.
3170Sstevel@tonic-gate  */
3180Sstevel@tonic-gate 
3190Sstevel@tonic-gate static void
3200Sstevel@tonic-gate packet_init_compression(void)
3210Sstevel@tonic-gate {
3220Sstevel@tonic-gate 	if (compression_buffer_ready == 1)
3230Sstevel@tonic-gate 		return;
3240Sstevel@tonic-gate 	compression_buffer_ready = 1;
3250Sstevel@tonic-gate 	buffer_init(&compression_buffer);
3260Sstevel@tonic-gate }
3270Sstevel@tonic-gate 
3280Sstevel@tonic-gate void
3290Sstevel@tonic-gate packet_start_compression(int level)
3300Sstevel@tonic-gate {
3310Sstevel@tonic-gate #ifdef ALTPRIVSEP
3320Sstevel@tonic-gate 	/* shouldn't happen! */
3330Sstevel@tonic-gate 	if (packet_monitor)
3340Sstevel@tonic-gate 		fatal("INTERNAL ERROR: The monitor cannot compress.");
3350Sstevel@tonic-gate #endif /* ALTPRIVSEP */
3360Sstevel@tonic-gate 
3370Sstevel@tonic-gate 	if (packet_compression && !compat20)
3380Sstevel@tonic-gate 		fatal("Compression already enabled.");
3390Sstevel@tonic-gate 	packet_compression = 1;
3400Sstevel@tonic-gate 	packet_init_compression();
3410Sstevel@tonic-gate 	buffer_compress_init_send(level);
3420Sstevel@tonic-gate 	buffer_compress_init_recv();
3430Sstevel@tonic-gate }
3440Sstevel@tonic-gate 
3450Sstevel@tonic-gate /*
3460Sstevel@tonic-gate  * Causes any further packets to be encrypted using the given key.  The same
3470Sstevel@tonic-gate  * key is used for both sending and reception.  However, both directions are
3480Sstevel@tonic-gate  * encrypted independently of each other.
3490Sstevel@tonic-gate  */
3500Sstevel@tonic-gate 
3510Sstevel@tonic-gate void
3520Sstevel@tonic-gate packet_set_encryption_key(const u_char *key, u_int keylen,
3530Sstevel@tonic-gate     int number)
3540Sstevel@tonic-gate {
3550Sstevel@tonic-gate 	Cipher *cipher = cipher_by_number(number);
3560Sstevel@tonic-gate 
3570Sstevel@tonic-gate 	if (cipher == NULL)
3580Sstevel@tonic-gate 		fatal("packet_set_encryption_key: unknown cipher number %d", number);
3590Sstevel@tonic-gate 	if (keylen < 20)
3600Sstevel@tonic-gate 		fatal("packet_set_encryption_key: keylen too small: %d", keylen);
3610Sstevel@tonic-gate 	if (keylen > SSH_SESSION_KEY_LENGTH)
3620Sstevel@tonic-gate 		fatal("packet_set_encryption_key: keylen too big: %d", keylen);
3630Sstevel@tonic-gate 	memcpy(ssh1_key, key, keylen);
3640Sstevel@tonic-gate 	ssh1_keylen = keylen;
3650Sstevel@tonic-gate 	cipher_init(&send_context, cipher, key, keylen, NULL, 0, CIPHER_ENCRYPT);
3660Sstevel@tonic-gate 	cipher_init(&receive_context, cipher, key, keylen, NULL, 0, CIPHER_DECRYPT);
3670Sstevel@tonic-gate }
3680Sstevel@tonic-gate 
3690Sstevel@tonic-gate u_int
3700Sstevel@tonic-gate packet_get_encryption_key(u_char *key)
3710Sstevel@tonic-gate {
3720Sstevel@tonic-gate 	if (key == NULL)
3730Sstevel@tonic-gate 		return (ssh1_keylen);
3740Sstevel@tonic-gate 	memcpy(key, ssh1_key, ssh1_keylen);
3750Sstevel@tonic-gate 	return (ssh1_keylen);
3760Sstevel@tonic-gate }
3770Sstevel@tonic-gate 
3780Sstevel@tonic-gate /* Start constructing a packet to send. */
3790Sstevel@tonic-gate void
3800Sstevel@tonic-gate packet_start(u_char type)
3810Sstevel@tonic-gate {
3820Sstevel@tonic-gate 	u_char buf[9];
3830Sstevel@tonic-gate 	int len;
3840Sstevel@tonic-gate 
3850Sstevel@tonic-gate 	DBG(debug("packet_start[%d]", type));
3860Sstevel@tonic-gate 	len = compat20 ? 6 : 9;
3870Sstevel@tonic-gate 	memset(buf, 0, len - 1);
3880Sstevel@tonic-gate 	buf[len - 1] = type;
3890Sstevel@tonic-gate 	buffer_clear(&outgoing_packet);
3900Sstevel@tonic-gate 	buffer_append(&outgoing_packet, buf, len);
3910Sstevel@tonic-gate }
3920Sstevel@tonic-gate 
3930Sstevel@tonic-gate /* Append payload. */
3940Sstevel@tonic-gate void
3950Sstevel@tonic-gate packet_put_char(int value)
3960Sstevel@tonic-gate {
3970Sstevel@tonic-gate 	char ch = value;
3980Sstevel@tonic-gate 
3990Sstevel@tonic-gate 	buffer_append(&outgoing_packet, &ch, 1);
4000Sstevel@tonic-gate }
401*5562Sjp161948 
4020Sstevel@tonic-gate void
4030Sstevel@tonic-gate packet_put_int(u_int value)
4040Sstevel@tonic-gate {
4050Sstevel@tonic-gate 	buffer_put_int(&outgoing_packet, value);
4060Sstevel@tonic-gate }
407*5562Sjp161948 
4080Sstevel@tonic-gate void
4090Sstevel@tonic-gate packet_put_string(const void *buf, u_int len)
4100Sstevel@tonic-gate {
4110Sstevel@tonic-gate 	buffer_put_string(&outgoing_packet, buf, len);
4120Sstevel@tonic-gate }
413*5562Sjp161948 
4140Sstevel@tonic-gate void
4150Sstevel@tonic-gate packet_put_cstring(const char *str)
4160Sstevel@tonic-gate {
4170Sstevel@tonic-gate 	buffer_put_cstring(&outgoing_packet, str);
4180Sstevel@tonic-gate }
419*5562Sjp161948 
4200Sstevel@tonic-gate void
4210Sstevel@tonic-gate packet_put_ascii_cstring(const char *str)
4220Sstevel@tonic-gate {
4230Sstevel@tonic-gate 	buffer_put_ascii_cstring(&outgoing_packet, str);
4240Sstevel@tonic-gate }
4250Sstevel@tonic-gate void
4260Sstevel@tonic-gate packet_put_utf8_cstring(const u_char *str)
4270Sstevel@tonic-gate {
4280Sstevel@tonic-gate 	buffer_put_utf8_cstring(&outgoing_packet, str);
4290Sstevel@tonic-gate }
4300Sstevel@tonic-gate #if 0
4310Sstevel@tonic-gate void
4320Sstevel@tonic-gate packet_put_ascii_string(const void *buf, u_int len)
4330Sstevel@tonic-gate {
4340Sstevel@tonic-gate 	buffer_put_ascii_string(&outgoing_packet, buf, len);
4350Sstevel@tonic-gate }
4360Sstevel@tonic-gate void
4370Sstevel@tonic-gate packet_put_utf8_string(const void *buf, u_int len)
4380Sstevel@tonic-gate {
4390Sstevel@tonic-gate 	buffer_put_utf8_string(&outgoing_packet, buf, len);
4400Sstevel@tonic-gate }
4410Sstevel@tonic-gate #endif
4420Sstevel@tonic-gate void
4430Sstevel@tonic-gate packet_put_raw(const void *buf, u_int len)
4440Sstevel@tonic-gate {
4450Sstevel@tonic-gate 	buffer_append(&outgoing_packet, buf, len);
4460Sstevel@tonic-gate }
447*5562Sjp161948 
4480Sstevel@tonic-gate void
4490Sstevel@tonic-gate packet_put_bignum(BIGNUM * value)
4500Sstevel@tonic-gate {
4510Sstevel@tonic-gate 	buffer_put_bignum(&outgoing_packet, value);
4520Sstevel@tonic-gate }
453*5562Sjp161948 
4540Sstevel@tonic-gate void
4550Sstevel@tonic-gate packet_put_bignum2(BIGNUM * value)
4560Sstevel@tonic-gate {
4570Sstevel@tonic-gate 	buffer_put_bignum2(&outgoing_packet, value);
4580Sstevel@tonic-gate }
4590Sstevel@tonic-gate 
4600Sstevel@tonic-gate /*
4610Sstevel@tonic-gate  * Finalizes and sends the packet.  If the encryption key has been set,
4620Sstevel@tonic-gate  * encrypts the packet before sending.
4630Sstevel@tonic-gate  */
4640Sstevel@tonic-gate 
4650Sstevel@tonic-gate static void
4660Sstevel@tonic-gate packet_send1(void)
4670Sstevel@tonic-gate {
4680Sstevel@tonic-gate 	u_char buf[8], *cp;
4690Sstevel@tonic-gate 	int i, padding, len;
4700Sstevel@tonic-gate 	u_int checksum;
471*5562Sjp161948 	u_int32_t rnd = 0;
4720Sstevel@tonic-gate 
4730Sstevel@tonic-gate 	/*
4740Sstevel@tonic-gate 	 * If using packet compression, compress the payload of the outgoing
4750Sstevel@tonic-gate 	 * packet.
4760Sstevel@tonic-gate 	 */
4770Sstevel@tonic-gate 	if (packet_compression) {
4780Sstevel@tonic-gate 		buffer_clear(&compression_buffer);
4790Sstevel@tonic-gate 		/* Skip padding. */
4800Sstevel@tonic-gate 		buffer_consume(&outgoing_packet, 8);
4810Sstevel@tonic-gate 		/* padding */
4820Sstevel@tonic-gate 		buffer_append(&compression_buffer, "\0\0\0\0\0\0\0\0", 8);
4830Sstevel@tonic-gate 		buffer_compress(&outgoing_packet, &compression_buffer);
4840Sstevel@tonic-gate 		buffer_clear(&outgoing_packet);
4850Sstevel@tonic-gate 		buffer_append(&outgoing_packet, buffer_ptr(&compression_buffer),
4860Sstevel@tonic-gate 		    buffer_len(&compression_buffer));
4870Sstevel@tonic-gate 	}
4880Sstevel@tonic-gate 	/* Compute packet length without padding (add checksum, remove padding). */
4890Sstevel@tonic-gate 	len = buffer_len(&outgoing_packet) + 4 - 8;
4900Sstevel@tonic-gate 
4910Sstevel@tonic-gate 	/* Insert padding. Initialized to zero in packet_start1() */
4920Sstevel@tonic-gate 	padding = 8 - len % 8;
4930Sstevel@tonic-gate 	if (!send_context.plaintext) {
4940Sstevel@tonic-gate 		cp = buffer_ptr(&outgoing_packet);
4950Sstevel@tonic-gate 		for (i = 0; i < padding; i++) {
4960Sstevel@tonic-gate 			if (i % 4 == 0)
497*5562Sjp161948 				rnd = arc4random();
498*5562Sjp161948 			cp[7 - i] = rnd & 0xff;
499*5562Sjp161948 			rnd >>= 8;
5000Sstevel@tonic-gate 		}
5010Sstevel@tonic-gate 	}
5020Sstevel@tonic-gate 	buffer_consume(&outgoing_packet, 8 - padding);
5030Sstevel@tonic-gate 
5040Sstevel@tonic-gate 	/* Add check bytes. */
5050Sstevel@tonic-gate 	checksum = ssh_crc32(buffer_ptr(&outgoing_packet),
5060Sstevel@tonic-gate 	    buffer_len(&outgoing_packet));
5070Sstevel@tonic-gate 	PUT_32BIT(buf, checksum);
5080Sstevel@tonic-gate 	buffer_append(&outgoing_packet, buf, 4);
5090Sstevel@tonic-gate 
5100Sstevel@tonic-gate #ifdef PACKET_DEBUG
5110Sstevel@tonic-gate 	fprintf(stderr, "packet_send plain: ");
5120Sstevel@tonic-gate 	buffer_dump(&outgoing_packet);
5130Sstevel@tonic-gate #endif
5140Sstevel@tonic-gate 
5150Sstevel@tonic-gate 	/* Append to output. */
5160Sstevel@tonic-gate 	PUT_32BIT(buf, len);
5170Sstevel@tonic-gate 	buffer_append(&output, buf, 4);
5180Sstevel@tonic-gate 	cp = buffer_append_space(&output, buffer_len(&outgoing_packet));
5190Sstevel@tonic-gate 	cipher_crypt(&send_context, cp, buffer_ptr(&outgoing_packet),
5200Sstevel@tonic-gate 	    buffer_len(&outgoing_packet));
5210Sstevel@tonic-gate 
5220Sstevel@tonic-gate #ifdef PACKET_DEBUG
5230Sstevel@tonic-gate 	fprintf(stderr, "encrypted: ");
5240Sstevel@tonic-gate 	buffer_dump(&output);
5250Sstevel@tonic-gate #endif
5260Sstevel@tonic-gate 
5270Sstevel@tonic-gate 	buffer_clear(&outgoing_packet);
5280Sstevel@tonic-gate 
5290Sstevel@tonic-gate 	/*
5300Sstevel@tonic-gate 	 * Note that the packet is now only buffered in output.  It won\'t be
5310Sstevel@tonic-gate 	 * actually sent until packet_write_wait or packet_write_poll is
5320Sstevel@tonic-gate 	 * called.
5330Sstevel@tonic-gate 	 */
5340Sstevel@tonic-gate }
5350Sstevel@tonic-gate 
5360Sstevel@tonic-gate void
5370Sstevel@tonic-gate set_newkeys(int mode)
5380Sstevel@tonic-gate {
5390Sstevel@tonic-gate 	Enc *enc;
5400Sstevel@tonic-gate 	Mac *mac;
5410Sstevel@tonic-gate 	Comp *comp;
5420Sstevel@tonic-gate 	CipherContext *cc;
543*5562Sjp161948 	u_int64_t *max_blocks;
544*5562Sjp161948 	int crypt_type;
5450Sstevel@tonic-gate 
546*5562Sjp161948 	debug2("set_newkeys: mode %d", mode);
5470Sstevel@tonic-gate 
5480Sstevel@tonic-gate 	if (mode == MODE_OUT) {
5490Sstevel@tonic-gate 		cc = &send_context;
550*5562Sjp161948 		crypt_type = CIPHER_ENCRYPT;
551*5562Sjp161948 		p_send.packets = p_send.blocks = 0;
552*5562Sjp161948 		max_blocks = &max_blocks_out;
5530Sstevel@tonic-gate 	} else {
5540Sstevel@tonic-gate 		cc = &receive_context;
555*5562Sjp161948 		crypt_type = CIPHER_DECRYPT;
556*5562Sjp161948 		p_read.packets = p_read.blocks = 0;
557*5562Sjp161948 		max_blocks = &max_blocks_in;
5580Sstevel@tonic-gate 	}
5590Sstevel@tonic-gate 	if (newkeys[mode] != NULL) {
560*5562Sjp161948 		debug("set_newkeys: rekeying");
5610Sstevel@tonic-gate 		cipher_cleanup(cc);
562*5562Sjp161948 		free_keys(newkeys[mode]);
5630Sstevel@tonic-gate 	}
5640Sstevel@tonic-gate 	newkeys[mode] = kex_get_newkeys(mode);
5650Sstevel@tonic-gate 	if (newkeys[mode] == NULL)
5660Sstevel@tonic-gate 		fatal("newkeys: no keys for mode %d", mode);
5670Sstevel@tonic-gate 	enc  = &newkeys[mode]->enc;
5680Sstevel@tonic-gate 	mac  = &newkeys[mode]->mac;
5690Sstevel@tonic-gate 	comp = &newkeys[mode]->comp;
5700Sstevel@tonic-gate 	if (mac->md != NULL)
5710Sstevel@tonic-gate 		mac->enabled = 1;
5720Sstevel@tonic-gate 	DBG(debug("cipher_init_context: %d", mode));
5730Sstevel@tonic-gate 	cipher_init(cc, enc->cipher, enc->key, enc->key_len,
574*5562Sjp161948 	    enc->iv, enc->block_size, crypt_type);
5750Sstevel@tonic-gate 	/* Deleting the keys does not gain extra security */
5760Sstevel@tonic-gate 	/* memset(enc->iv,  0, enc->block_size);
5770Sstevel@tonic-gate 	   memset(enc->key, 0, enc->key_len); */
5780Sstevel@tonic-gate 	if (comp->type != 0 && comp->enabled == 0) {
5790Sstevel@tonic-gate 		packet_init_compression();
5800Sstevel@tonic-gate 		if (mode == MODE_OUT)
5810Sstevel@tonic-gate 			buffer_compress_init_send(6);
5820Sstevel@tonic-gate 		else
5830Sstevel@tonic-gate 			buffer_compress_init_recv();
5840Sstevel@tonic-gate 		comp->enabled = 1;
5850Sstevel@tonic-gate 	}
586*5562Sjp161948 
587*5562Sjp161948 	/*
588*5562Sjp161948 	 * In accordance to the RFCs listed below we enforce the key
589*5562Sjp161948 	 * re-exchange for:
590*5562Sjp161948 	 *
591*5562Sjp161948 	 * - every 1GB of transmitted data if the selected cipher block size
592*5562Sjp161948 	 *   is less than 16 bytes (3DES, Blowfish)
593*5562Sjp161948 	 * - every 2^(2*B) cipher blocks transmitted (B is block size in bytes)
594*5562Sjp161948 	 *   if the cipher block size is greater than or equal to 16 bytes (AES)
595*5562Sjp161948 	 * - and we never send more than 2^32 SSH packets using the same keys.
596*5562Sjp161948 	 *   The recommendation of 2^31 packets is not enforced here but in
597*5562Sjp161948 	 *   packet_need_rekeying(). There is also a hard check in
598*5562Sjp161948 	 *   packet_send2_wrapped() that we don't send more than 2^32 packets.
599*5562Sjp161948 	 *
600*5562Sjp161948 	 * Note that if the SSH_BUG_NOREKEY compatibility flag is set then no
601*5562Sjp161948 	 * automatic rekeying is performed nor do we enforce the 3rd rule.
602*5562Sjp161948 	 * This means that we can be always forced by the opposite side to never
603*5562Sjp161948 	 * initiate automatic key re-exchange. This might change in the future.
604*5562Sjp161948 	 *
605*5562Sjp161948 	 * The RekeyLimit option keyword may only enforce more frequent key
606*5562Sjp161948 	 * renegotiation, never less. For more information on key renegotiation,
607*5562Sjp161948 	 * see:
608*5562Sjp161948 	 *
609*5562Sjp161948 	 * - RFC 4253 (SSH Transport Layer Protocol), section "9. Key
610*5562Sjp161948 	 *   Re-Exchange"
611*5562Sjp161948 	 * - RFC 4344 (SSH Transport Layer Encryption Modes), sections "3.
612*5562Sjp161948 	 *   Rekeying" and "6.1 Rekeying Considerations"
613*5562Sjp161948 	 */
614*5562Sjp161948 	if (enc->block_size >= 16)
615*5562Sjp161948 		*max_blocks = (u_int64_t)1 << (enc->block_size * 2);
616*5562Sjp161948 	else
617*5562Sjp161948 		*max_blocks = ((u_int64_t)1 << 30) / enc->block_size;
618*5562Sjp161948 
619*5562Sjp161948 	if (rekey_limit)
620*5562Sjp161948 		*max_blocks = MIN(*max_blocks, rekey_limit / enc->block_size);
621*5562Sjp161948 }
622*5562Sjp161948 
623*5562Sjp161948 void
624*5562Sjp161948 free_keys(Newkeys *keys)
625*5562Sjp161948 {
626*5562Sjp161948 	Enc *enc;
627*5562Sjp161948 	Mac *mac;
628*5562Sjp161948 	Comp *comp;
629*5562Sjp161948 
630*5562Sjp161948 	enc  = &keys->enc;
631*5562Sjp161948 	mac  = &keys->mac;
632*5562Sjp161948 	comp = &keys->comp;
633*5562Sjp161948 	memset(mac->key, 0, mac->key_len);
634*5562Sjp161948 	xfree(enc->name);
635*5562Sjp161948 	xfree(enc->iv);
636*5562Sjp161948 	xfree(enc->key);
637*5562Sjp161948 	xfree(mac->name);
638*5562Sjp161948 	xfree(mac->key);
639*5562Sjp161948 	xfree(comp->name);
640*5562Sjp161948 	xfree(keys);
6410Sstevel@tonic-gate }
6420Sstevel@tonic-gate 
6430Sstevel@tonic-gate /*
6440Sstevel@tonic-gate  * Finalize packet in SSH2 format (compress, mac, encrypt, enqueue)
6450Sstevel@tonic-gate  */
6460Sstevel@tonic-gate static void
647*5562Sjp161948 packet_send2_wrapped(void)
6480Sstevel@tonic-gate {
6490Sstevel@tonic-gate 	u_char type, *cp, *macbuf = NULL;
6500Sstevel@tonic-gate 	u_char padlen, pad;
6510Sstevel@tonic-gate 	u_int packet_length = 0;
6520Sstevel@tonic-gate 	u_int i, len;
653*5562Sjp161948 	u_int32_t rnd = 0;
6540Sstevel@tonic-gate 	Enc *enc   = NULL;
6550Sstevel@tonic-gate 	Mac *mac   = NULL;
6560Sstevel@tonic-gate 	Comp *comp = NULL;
6570Sstevel@tonic-gate 	int block_size;
6580Sstevel@tonic-gate 
6590Sstevel@tonic-gate 	if (newkeys[MODE_OUT] != NULL) {
6600Sstevel@tonic-gate 		enc  = &newkeys[MODE_OUT]->enc;
6610Sstevel@tonic-gate 		mac  = &newkeys[MODE_OUT]->mac;
6620Sstevel@tonic-gate 		comp = &newkeys[MODE_OUT]->comp;
6630Sstevel@tonic-gate 	}
6640Sstevel@tonic-gate 	block_size = enc ? enc->block_size : 8;
6650Sstevel@tonic-gate 
6660Sstevel@tonic-gate 	cp = buffer_ptr(&outgoing_packet);
6670Sstevel@tonic-gate 	type = cp[5];
6680Sstevel@tonic-gate 
6690Sstevel@tonic-gate #ifdef PACKET_DEBUG
6700Sstevel@tonic-gate 	fprintf(stderr, "plain:     ");
6710Sstevel@tonic-gate 	buffer_dump(&outgoing_packet);
6720Sstevel@tonic-gate #endif
6730Sstevel@tonic-gate 
6740Sstevel@tonic-gate 	if (comp && comp->enabled) {
6750Sstevel@tonic-gate 		len = buffer_len(&outgoing_packet);
6760Sstevel@tonic-gate 		/* skip header, compress only payload */
6770Sstevel@tonic-gate 		buffer_consume(&outgoing_packet, 5);
6780Sstevel@tonic-gate 		buffer_clear(&compression_buffer);
6790Sstevel@tonic-gate 		buffer_compress(&outgoing_packet, &compression_buffer);
6800Sstevel@tonic-gate 		buffer_clear(&outgoing_packet);
6810Sstevel@tonic-gate 		buffer_append(&outgoing_packet, "\0\0\0\0\0", 5);
6820Sstevel@tonic-gate 		buffer_append(&outgoing_packet, buffer_ptr(&compression_buffer),
6830Sstevel@tonic-gate 		    buffer_len(&compression_buffer));
6840Sstevel@tonic-gate 		DBG(debug("compression: raw %d compressed %d", len,
6850Sstevel@tonic-gate 		    buffer_len(&outgoing_packet)));
6860Sstevel@tonic-gate 	}
6870Sstevel@tonic-gate 
6880Sstevel@tonic-gate 	/* sizeof (packet_len + pad_len + payload) */
6890Sstevel@tonic-gate 	len = buffer_len(&outgoing_packet);
6900Sstevel@tonic-gate 
6910Sstevel@tonic-gate 	/*
6920Sstevel@tonic-gate 	 * calc size of padding, alloc space, get random data,
6930Sstevel@tonic-gate 	 * minimum padding is 4 bytes
6940Sstevel@tonic-gate 	 */
6950Sstevel@tonic-gate 	padlen = block_size - (len % block_size);
6960Sstevel@tonic-gate 	if (padlen < 4)
6970Sstevel@tonic-gate 		padlen += block_size;
6980Sstevel@tonic-gate 	if (extra_pad) {
6990Sstevel@tonic-gate 		/* will wrap if extra_pad+padlen > 255 */
7000Sstevel@tonic-gate 		extra_pad  = roundup(extra_pad, block_size);
7010Sstevel@tonic-gate 		pad = extra_pad - ((len + padlen) % extra_pad);
7020Sstevel@tonic-gate 		debug3("packet_send2: adding %d (len %d padlen %d extra_pad %d)",
7030Sstevel@tonic-gate 		    pad, len, padlen, extra_pad);
7040Sstevel@tonic-gate 		padlen += pad;
7050Sstevel@tonic-gate 		extra_pad = 0;
7060Sstevel@tonic-gate 	}
7070Sstevel@tonic-gate 	cp = buffer_append_space(&outgoing_packet, padlen);
7080Sstevel@tonic-gate 	if (enc && !send_context.plaintext) {
7090Sstevel@tonic-gate 		/* random padding */
7100Sstevel@tonic-gate 		for (i = 0; i < padlen; i++) {
7110Sstevel@tonic-gate 			if (i % 4 == 0)
712*5562Sjp161948 				rnd = arc4random();
713*5562Sjp161948 			cp[i] = rnd & 0xff;
714*5562Sjp161948 			rnd >>= 8;
7150Sstevel@tonic-gate 		}
7160Sstevel@tonic-gate 	} else {
7170Sstevel@tonic-gate 		/* clear padding */
7180Sstevel@tonic-gate 		memset(cp, 0, padlen);
7190Sstevel@tonic-gate 	}
7200Sstevel@tonic-gate 	/* packet_length includes payload, padding and padding length field */
7210Sstevel@tonic-gate 	packet_length = buffer_len(&outgoing_packet) - 4;
7220Sstevel@tonic-gate 	cp = buffer_ptr(&outgoing_packet);
7230Sstevel@tonic-gate 	PUT_32BIT(cp, packet_length);
7240Sstevel@tonic-gate 	cp[4] = padlen;
7250Sstevel@tonic-gate 	DBG(debug("send: len %d (includes padlen %d)", packet_length+4, padlen));
7260Sstevel@tonic-gate 
7270Sstevel@tonic-gate 	/* compute MAC over seqnr and packet(length fields, payload, padding) */
7280Sstevel@tonic-gate 	if (mac && mac->enabled) {
729*5562Sjp161948 		macbuf = mac_compute(mac, p_send.seqnr,
7300Sstevel@tonic-gate 		    buffer_ptr(&outgoing_packet),
7310Sstevel@tonic-gate 		    buffer_len(&outgoing_packet));
732*5562Sjp161948 		DBG(debug("done calc MAC out #%d", p_send.seqnr));
7330Sstevel@tonic-gate 	}
7340Sstevel@tonic-gate 	/* encrypt packet and append to output buffer. */
7350Sstevel@tonic-gate 	cp = buffer_append_space(&output, buffer_len(&outgoing_packet));
7360Sstevel@tonic-gate 	cipher_crypt(&send_context, cp, buffer_ptr(&outgoing_packet),
7370Sstevel@tonic-gate 	    buffer_len(&outgoing_packet));
7380Sstevel@tonic-gate 	/* append unencrypted MAC */
7390Sstevel@tonic-gate 	if (mac && mac->enabled)
7400Sstevel@tonic-gate 		buffer_append(&output, (char *)macbuf, mac->mac_len);
7410Sstevel@tonic-gate #ifdef PACKET_DEBUG
7420Sstevel@tonic-gate 	fprintf(stderr, "encrypted: ");
7430Sstevel@tonic-gate 	buffer_dump(&output);
7440Sstevel@tonic-gate #endif
7450Sstevel@tonic-gate 	/* increment sequence number for outgoing packets */
746*5562Sjp161948 	if (++p_send.seqnr == 0)
7470Sstevel@tonic-gate 		log("outgoing seqnr wraps around");
748*5562Sjp161948 
749*5562Sjp161948 	/*
750*5562Sjp161948 	 * RFC 4344: 3.1. First Rekeying Recommendation
751*5562Sjp161948 	 *
752*5562Sjp161948 	 * "Because of possible information leakage through the MAC tag after a
753*5562Sjp161948 	 * key exchange, .... an SSH implementation SHOULD NOT send more than
754*5562Sjp161948 	 * 2**32 packets before rekeying again."
755*5562Sjp161948 	 *
756*5562Sjp161948 	 * The code below is a hard check so that we are sure we don't go across
757*5562Sjp161948 	 * the suggestion. However, since the largest cipher block size we have
758*5562Sjp161948 	 * (AES) is 16 bytes we can't reach 2^32 SSH packets encrypted with the
759*5562Sjp161948 	 * same key while performing periodic rekeying.
760*5562Sjp161948 	 */
761*5562Sjp161948 	if (++p_send.packets == 0)
762*5562Sjp161948 		if (!(datafellows & SSH_BUG_NOREKEY))
763*5562Sjp161948 			fatal("too many packets encrypted with same key");
764*5562Sjp161948 	p_send.blocks += (packet_length + 4) / block_size;
7650Sstevel@tonic-gate 	buffer_clear(&outgoing_packet);
7660Sstevel@tonic-gate 
7670Sstevel@tonic-gate 	if (type == SSH2_MSG_NEWKEYS)
7680Sstevel@tonic-gate #ifdef ALTPRIVSEP
7690Sstevel@tonic-gate 		/* set_newkeys(MODE_OUT) in client, server, but not monitor */
7700Sstevel@tonic-gate 		if (!packet_is_server() && !packet_is_monitor())
7710Sstevel@tonic-gate #endif /* ALTPRIVSEP */
7720Sstevel@tonic-gate 		set_newkeys(MODE_OUT);
7730Sstevel@tonic-gate }
7740Sstevel@tonic-gate 
775*5562Sjp161948 static void
776*5562Sjp161948 packet_send2(void)
777*5562Sjp161948 {
778*5562Sjp161948 	static int rekeying = 0;
779*5562Sjp161948 	struct packet *p;
780*5562Sjp161948 	u_char type, *cp;
781*5562Sjp161948 
782*5562Sjp161948 	cp = buffer_ptr(&outgoing_packet);
783*5562Sjp161948 	type = cp[5];
784*5562Sjp161948 
785*5562Sjp161948 	/* during rekeying we can only send key exchange messages */
786*5562Sjp161948 	if (rekeying) {
787*5562Sjp161948 		if (!((type >= SSH2_MSG_TRANSPORT_MIN) &&
788*5562Sjp161948 		    (type <= SSH2_MSG_TRANSPORT_MAX))) {
789*5562Sjp161948 			debug("enqueue packet: %u", type);
790*5562Sjp161948 			p = xmalloc(sizeof(*p));
791*5562Sjp161948 			p->type = type;
792*5562Sjp161948 			memcpy(&p->payload, &outgoing_packet, sizeof(Buffer));
793*5562Sjp161948 			buffer_init(&outgoing_packet);
794*5562Sjp161948 			TAILQ_INSERT_TAIL(&outgoing, p, next);
795*5562Sjp161948 			return;
796*5562Sjp161948 		}
797*5562Sjp161948 	}
798*5562Sjp161948 
799*5562Sjp161948 	/* rekeying starts with sending KEXINIT */
800*5562Sjp161948 	if (type == SSH2_MSG_KEXINIT)
801*5562Sjp161948 		rekeying = 1;
802*5562Sjp161948 
803*5562Sjp161948 	packet_send2_wrapped();
804*5562Sjp161948 
805*5562Sjp161948 	/* after a NEWKEYS message we can send the complete queue */
806*5562Sjp161948 	if (type == SSH2_MSG_NEWKEYS) {
807*5562Sjp161948 		rekeying = 0;
808*5562Sjp161948 		while ((p = TAILQ_FIRST(&outgoing)) != NULL) {
809*5562Sjp161948 			type = p->type;
810*5562Sjp161948 			debug("dequeue packet: %u", type);
811*5562Sjp161948 			buffer_free(&outgoing_packet);
812*5562Sjp161948 			memcpy(&outgoing_packet, &p->payload, sizeof(Buffer));
813*5562Sjp161948 			TAILQ_REMOVE(&outgoing, p, next);
814*5562Sjp161948 			xfree(p);
815*5562Sjp161948 			packet_send2_wrapped();
816*5562Sjp161948 		}
817*5562Sjp161948 	}
818*5562Sjp161948 }
819*5562Sjp161948 
8200Sstevel@tonic-gate void
8210Sstevel@tonic-gate packet_send(void)
8220Sstevel@tonic-gate {
8230Sstevel@tonic-gate 	if (compat20)
8240Sstevel@tonic-gate 		packet_send2();
8250Sstevel@tonic-gate 	else
8260Sstevel@tonic-gate 		packet_send1();
8270Sstevel@tonic-gate 	DBG(debug("packet_send done"));
8280Sstevel@tonic-gate }
8290Sstevel@tonic-gate 
8300Sstevel@tonic-gate /*
8310Sstevel@tonic-gate  * Waits until a packet has been received, and returns its type.  Note that
8320Sstevel@tonic-gate  * no other data is processed until this returns, so this function should not
8330Sstevel@tonic-gate  * be used during the interactive session.
8340Sstevel@tonic-gate  */
8350Sstevel@tonic-gate 
8360Sstevel@tonic-gate int
8370Sstevel@tonic-gate packet_read_seqnr(u_int32_t *seqnr_p)
8380Sstevel@tonic-gate {
8390Sstevel@tonic-gate 	int type, len;
8400Sstevel@tonic-gate 	fd_set *setp;
8410Sstevel@tonic-gate 	char buf[8192];
8420Sstevel@tonic-gate 	DBG(debug("packet_read()"));
8430Sstevel@tonic-gate 
8440Sstevel@tonic-gate 	setp = (fd_set *)xmalloc(howmany(connection_in+1, NFDBITS) *
8450Sstevel@tonic-gate 	    sizeof(fd_mask));
8460Sstevel@tonic-gate 
8470Sstevel@tonic-gate 	/* Since we are blocking, ensure that all written packets have been sent. */
8480Sstevel@tonic-gate 	packet_write_wait();
8490Sstevel@tonic-gate 
8500Sstevel@tonic-gate 	/* Stay in the loop until we have received a complete packet. */
8510Sstevel@tonic-gate 	for (;;) {
8520Sstevel@tonic-gate 		/* Try to read a packet from the buffer. */
8530Sstevel@tonic-gate 		type = packet_read_poll_seqnr(seqnr_p);
8540Sstevel@tonic-gate 		if (!compat20 && (
8550Sstevel@tonic-gate 		    type == SSH_SMSG_SUCCESS
8560Sstevel@tonic-gate 		    || type == SSH_SMSG_FAILURE
8570Sstevel@tonic-gate 		    || type == SSH_CMSG_EOF
8580Sstevel@tonic-gate 		    || type == SSH_CMSG_EXIT_CONFIRMATION))
8590Sstevel@tonic-gate 			packet_check_eom();
8600Sstevel@tonic-gate 		/* If we got a packet, return it. */
8610Sstevel@tonic-gate 		if (type != SSH_MSG_NONE) {
8620Sstevel@tonic-gate 			xfree(setp);
8630Sstevel@tonic-gate 			return type;
8640Sstevel@tonic-gate 		}
8650Sstevel@tonic-gate 		/*
8660Sstevel@tonic-gate 		 * Otherwise, wait for some data to arrive, add it to the
8670Sstevel@tonic-gate 		 * buffer, and try again.
8680Sstevel@tonic-gate 		 */
8690Sstevel@tonic-gate 		memset(setp, 0, howmany(connection_in + 1, NFDBITS) *
8700Sstevel@tonic-gate 		    sizeof(fd_mask));
8710Sstevel@tonic-gate 		FD_SET(connection_in, setp);
8720Sstevel@tonic-gate 
8730Sstevel@tonic-gate 		/* Wait for some data to arrive. */
8740Sstevel@tonic-gate 		while (select(connection_in + 1, setp, NULL, NULL, NULL) == -1 &&
8750Sstevel@tonic-gate 		    (errno == EAGAIN || errno == EINTR))
8760Sstevel@tonic-gate 			;
8770Sstevel@tonic-gate 
8780Sstevel@tonic-gate 		/* Read data from the socket. */
8790Sstevel@tonic-gate 		len = read(connection_in, buf, sizeof(buf));
8800Sstevel@tonic-gate 		if (len == 0) {
8810Sstevel@tonic-gate 			log("Connection closed by %.200s", get_remote_ipaddr());
8820Sstevel@tonic-gate 			fatal_cleanup();
8830Sstevel@tonic-gate 		}
8840Sstevel@tonic-gate 		if (len < 0)
8850Sstevel@tonic-gate 			fatal("Read from socket failed: %.100s", strerror(errno));
8860Sstevel@tonic-gate 		/* Append it to the buffer. */
8870Sstevel@tonic-gate 		packet_process_incoming(buf, len);
8880Sstevel@tonic-gate 	}
8890Sstevel@tonic-gate 	/* NOTREACHED */
8900Sstevel@tonic-gate }
8910Sstevel@tonic-gate 
8920Sstevel@tonic-gate int
8930Sstevel@tonic-gate packet_read(void)
8940Sstevel@tonic-gate {
8950Sstevel@tonic-gate 	return packet_read_seqnr(NULL);
8960Sstevel@tonic-gate }
8970Sstevel@tonic-gate 
8980Sstevel@tonic-gate /*
8990Sstevel@tonic-gate  * Waits until a packet has been received, verifies that its type matches
9000Sstevel@tonic-gate  * that given, and gives a fatal error and exits if there is a mismatch.
9010Sstevel@tonic-gate  */
9020Sstevel@tonic-gate 
9030Sstevel@tonic-gate void
9040Sstevel@tonic-gate packet_read_expect(int expected_type)
9050Sstevel@tonic-gate {
9060Sstevel@tonic-gate 	int type;
9070Sstevel@tonic-gate 
9080Sstevel@tonic-gate 	type = packet_read();
9090Sstevel@tonic-gate 	if (type != expected_type)
9100Sstevel@tonic-gate 		packet_disconnect("Protocol error: expected packet type %d, got %d",
9110Sstevel@tonic-gate 		    expected_type, type);
9120Sstevel@tonic-gate }
9130Sstevel@tonic-gate 
9140Sstevel@tonic-gate /* Checks if a full packet is available in the data received so far via
9150Sstevel@tonic-gate  * packet_process_incoming.  If so, reads the packet; otherwise returns
9160Sstevel@tonic-gate  * SSH_MSG_NONE.  This does not wait for data from the connection.
9170Sstevel@tonic-gate  *
9180Sstevel@tonic-gate  * SSH_MSG_DISCONNECT is handled specially here.  Also,
9190Sstevel@tonic-gate  * SSH_MSG_IGNORE messages are skipped by this function and are never returned
9200Sstevel@tonic-gate  * to higher levels.
9210Sstevel@tonic-gate  */
9220Sstevel@tonic-gate 
9230Sstevel@tonic-gate static int
9240Sstevel@tonic-gate packet_read_poll1(void)
9250Sstevel@tonic-gate {
9260Sstevel@tonic-gate 	u_int len, padded_len;
9270Sstevel@tonic-gate 	u_char *cp, type;
9280Sstevel@tonic-gate 	u_int checksum, stored_checksum;
9290Sstevel@tonic-gate 
9300Sstevel@tonic-gate 	/* Check if input size is less than minimum packet size. */
9310Sstevel@tonic-gate 	if (buffer_len(&input) < 4 + 8)
9320Sstevel@tonic-gate 		return SSH_MSG_NONE;
9330Sstevel@tonic-gate 	/* Get length of incoming packet. */
9340Sstevel@tonic-gate 	cp = buffer_ptr(&input);
9350Sstevel@tonic-gate 	len = GET_32BIT(cp);
9360Sstevel@tonic-gate 	if (len < 1 + 2 + 2 || len > 256 * 1024)
9370Sstevel@tonic-gate 		packet_disconnect("Bad packet length %d.", len);
9380Sstevel@tonic-gate 	padded_len = (len + 8) & ~7;
9390Sstevel@tonic-gate 
9400Sstevel@tonic-gate 	/* Check if the packet has been entirely received. */
9410Sstevel@tonic-gate 	if (buffer_len(&input) < 4 + padded_len)
9420Sstevel@tonic-gate 		return SSH_MSG_NONE;
9430Sstevel@tonic-gate 
9440Sstevel@tonic-gate 	/* The entire packet is in buffer. */
9450Sstevel@tonic-gate 
9460Sstevel@tonic-gate 	/* Consume packet length. */
9470Sstevel@tonic-gate 	buffer_consume(&input, 4);
9480Sstevel@tonic-gate 
9490Sstevel@tonic-gate 	/*
9500Sstevel@tonic-gate 	 * Cryptographic attack detector for ssh
9510Sstevel@tonic-gate 	 * (C)1998 CORE-SDI, Buenos Aires Argentina
9520Sstevel@tonic-gate 	 * Ariel Futoransky(futo@core-sdi.com)
9530Sstevel@tonic-gate 	 */
9543102Sjp161948 	if (!receive_context.plaintext) {
9553102Sjp161948 		switch (detect_attack(buffer_ptr(&input), padded_len, NULL)) {
9563102Sjp161948 		case DEATTACK_DETECTED:
9573102Sjp161948 			packet_disconnect("crc32 compensation attack: "
9583102Sjp161948 			    "network attack detected");
9593102Sjp161948 			break;
9603102Sjp161948 		case DEATTACK_DOS_DETECTED:
9613102Sjp161948 			packet_disconnect("deattack denial of "
9623102Sjp161948 			    "service detected");
9633102Sjp161948 			break;
9643102Sjp161948 		}
9653102Sjp161948 	}
9660Sstevel@tonic-gate 
9670Sstevel@tonic-gate 	/* Decrypt data to incoming_packet. */
9680Sstevel@tonic-gate 	buffer_clear(&incoming_packet);
9690Sstevel@tonic-gate 	cp = buffer_append_space(&incoming_packet, padded_len);
9700Sstevel@tonic-gate 	cipher_crypt(&receive_context, cp, buffer_ptr(&input), padded_len);
9710Sstevel@tonic-gate 
9720Sstevel@tonic-gate 	buffer_consume(&input, padded_len);
9730Sstevel@tonic-gate 
9740Sstevel@tonic-gate #ifdef PACKET_DEBUG
9750Sstevel@tonic-gate 	fprintf(stderr, "read_poll plain: ");
9760Sstevel@tonic-gate 	buffer_dump(&incoming_packet);
9770Sstevel@tonic-gate #endif
9780Sstevel@tonic-gate 
9790Sstevel@tonic-gate 	/* Compute packet checksum. */
9800Sstevel@tonic-gate 	checksum = ssh_crc32(buffer_ptr(&incoming_packet),
9810Sstevel@tonic-gate 	    buffer_len(&incoming_packet) - 4);
9820Sstevel@tonic-gate 
9830Sstevel@tonic-gate 	/* Skip padding. */
9840Sstevel@tonic-gate 	buffer_consume(&incoming_packet, 8 - len % 8);
9850Sstevel@tonic-gate 
9860Sstevel@tonic-gate 	/* Test check bytes. */
9870Sstevel@tonic-gate 	if (len != buffer_len(&incoming_packet))
9880Sstevel@tonic-gate 		packet_disconnect("packet_read_poll1: len %d != buffer_len %d.",
9890Sstevel@tonic-gate 		    len, buffer_len(&incoming_packet));
9900Sstevel@tonic-gate 
9910Sstevel@tonic-gate 	cp = (u_char *)buffer_ptr(&incoming_packet) + len - 4;
9920Sstevel@tonic-gate 	stored_checksum = GET_32BIT(cp);
9930Sstevel@tonic-gate 	if (checksum != stored_checksum)
9940Sstevel@tonic-gate 		packet_disconnect("Corrupted check bytes on input.");
9950Sstevel@tonic-gate 	buffer_consume_end(&incoming_packet, 4);
9960Sstevel@tonic-gate 
9970Sstevel@tonic-gate 	if (packet_compression) {
9980Sstevel@tonic-gate 		buffer_clear(&compression_buffer);
9990Sstevel@tonic-gate 		buffer_uncompress(&incoming_packet, &compression_buffer);
10000Sstevel@tonic-gate 		buffer_clear(&incoming_packet);
10010Sstevel@tonic-gate 		buffer_append(&incoming_packet, buffer_ptr(&compression_buffer),
10020Sstevel@tonic-gate 		    buffer_len(&compression_buffer));
10030Sstevel@tonic-gate 	}
10040Sstevel@tonic-gate 	type = buffer_get_char(&incoming_packet);
10050Sstevel@tonic-gate 	return type;
10060Sstevel@tonic-gate }
10070Sstevel@tonic-gate 
10080Sstevel@tonic-gate static int
10090Sstevel@tonic-gate packet_read_poll2(u_int32_t *seqnr_p)
10100Sstevel@tonic-gate {
10110Sstevel@tonic-gate 	static u_int packet_length = 0;
10120Sstevel@tonic-gate 	u_int padlen, need;
10130Sstevel@tonic-gate 	u_char *macbuf, *cp, type;
10140Sstevel@tonic-gate 	int maclen, block_size;
10150Sstevel@tonic-gate 	Enc *enc   = NULL;
10160Sstevel@tonic-gate 	Mac *mac   = NULL;
10170Sstevel@tonic-gate 	Comp *comp = NULL;
10180Sstevel@tonic-gate 
10190Sstevel@tonic-gate 	if (newkeys[MODE_IN] != NULL) {
10200Sstevel@tonic-gate 		enc  = &newkeys[MODE_IN]->enc;
10210Sstevel@tonic-gate 		mac  = &newkeys[MODE_IN]->mac;
10220Sstevel@tonic-gate 		comp = &newkeys[MODE_IN]->comp;
10230Sstevel@tonic-gate 	}
10240Sstevel@tonic-gate 	maclen = mac && mac->enabled ? mac->mac_len : 0;
10250Sstevel@tonic-gate 	block_size = enc ? enc->block_size : 8;
10260Sstevel@tonic-gate 
10270Sstevel@tonic-gate 	if (packet_length == 0) {
10280Sstevel@tonic-gate 		/*
10290Sstevel@tonic-gate 		 * check if input size is less than the cipher block size,
10300Sstevel@tonic-gate 		 * decrypt first block and extract length of incoming packet
10310Sstevel@tonic-gate 		 */
10320Sstevel@tonic-gate 		if (buffer_len(&input) < block_size)
10330Sstevel@tonic-gate 			return SSH_MSG_NONE;
10340Sstevel@tonic-gate 		buffer_clear(&incoming_packet);
10350Sstevel@tonic-gate 		cp = buffer_append_space(&incoming_packet, block_size);
10360Sstevel@tonic-gate 		cipher_crypt(&receive_context, cp, buffer_ptr(&input),
10370Sstevel@tonic-gate 		    block_size);
10380Sstevel@tonic-gate 		cp = buffer_ptr(&incoming_packet);
10390Sstevel@tonic-gate 		packet_length = GET_32BIT(cp);
10400Sstevel@tonic-gate 		if (packet_length < 1 + 4 || packet_length > 256 * 1024) {
10410Sstevel@tonic-gate 			buffer_dump(&incoming_packet);
10420Sstevel@tonic-gate 			packet_disconnect("Bad packet length %d.", packet_length);
10430Sstevel@tonic-gate 		}
1044*5562Sjp161948 		DBG(debug("input: packet len %u", packet_length + 4));
10450Sstevel@tonic-gate 		buffer_consume(&input, block_size);
10460Sstevel@tonic-gate 	}
10470Sstevel@tonic-gate 	/* we have a partial packet of block_size bytes */
10480Sstevel@tonic-gate 	need = 4 + packet_length - block_size;
10490Sstevel@tonic-gate 	DBG(debug("partial packet %d, need %d, maclen %d", block_size,
10500Sstevel@tonic-gate 	    need, maclen));
10510Sstevel@tonic-gate 	if (need % block_size != 0)
10520Sstevel@tonic-gate 		fatal("padding error: need %d block %d mod %d",
10530Sstevel@tonic-gate 		    need, block_size, need % block_size);
10540Sstevel@tonic-gate 	/*
10550Sstevel@tonic-gate 	 * check if the entire packet has been received and
10560Sstevel@tonic-gate 	 * decrypt into incoming_packet
10570Sstevel@tonic-gate 	 */
10580Sstevel@tonic-gate 	if (buffer_len(&input) < need + maclen)
10590Sstevel@tonic-gate 		return SSH_MSG_NONE;
10600Sstevel@tonic-gate #ifdef PACKET_DEBUG
10610Sstevel@tonic-gate 	fprintf(stderr, "read_poll enc/full: ");
10620Sstevel@tonic-gate 	buffer_dump(&input);
10630Sstevel@tonic-gate #endif
10640Sstevel@tonic-gate 	cp = buffer_append_space(&incoming_packet, need);
10650Sstevel@tonic-gate 	cipher_crypt(&receive_context, cp, buffer_ptr(&input), need);
10660Sstevel@tonic-gate 	buffer_consume(&input, need);
10670Sstevel@tonic-gate 	/*
10680Sstevel@tonic-gate 	 * compute MAC over seqnr and packet,
10690Sstevel@tonic-gate 	 * increment sequence number for incoming packet
10700Sstevel@tonic-gate 	 */
10710Sstevel@tonic-gate 	if (mac && mac->enabled) {
1072*5562Sjp161948 		macbuf = mac_compute(mac, p_read.seqnr,
10730Sstevel@tonic-gate 		    buffer_ptr(&incoming_packet),
10740Sstevel@tonic-gate 		    buffer_len(&incoming_packet));
10750Sstevel@tonic-gate 		if (memcmp(macbuf, buffer_ptr(&input), mac->mac_len) != 0)
10760Sstevel@tonic-gate 			packet_disconnect("Corrupted MAC on input.");
1077*5562Sjp161948 		DBG(debug("MAC #%d ok", p_read.seqnr));
10780Sstevel@tonic-gate 		buffer_consume(&input, mac->mac_len);
10790Sstevel@tonic-gate 	}
10800Sstevel@tonic-gate 	if (seqnr_p != NULL)
1081*5562Sjp161948 		*seqnr_p = p_read.seqnr;
1082*5562Sjp161948 	if (++p_read.seqnr == 0)
10830Sstevel@tonic-gate 		log("incoming seqnr wraps around");
10840Sstevel@tonic-gate 
1085*5562Sjp161948 	/* see above for the comment on "First Rekeying Recommendation" */
1086*5562Sjp161948 	if (++p_read.packets == 0)
1087*5562Sjp161948 		if (!(datafellows & SSH_BUG_NOREKEY))
1088*5562Sjp161948 			fatal("too many packets with same key");
1089*5562Sjp161948 	p_read.blocks += (packet_length + 4) / block_size;
1090*5562Sjp161948 
10910Sstevel@tonic-gate 	/* get padlen */
10920Sstevel@tonic-gate 	cp = buffer_ptr(&incoming_packet);
10930Sstevel@tonic-gate 	padlen = cp[4];
10940Sstevel@tonic-gate 	DBG(debug("input: padlen %d", padlen));
10950Sstevel@tonic-gate 	if (padlen < 4)
10960Sstevel@tonic-gate 		packet_disconnect("Corrupted padlen %d on input.", padlen);
10970Sstevel@tonic-gate 
10980Sstevel@tonic-gate 	/* skip packet size + padlen, discard padding */
10990Sstevel@tonic-gate 	buffer_consume(&incoming_packet, 4 + 1);
11000Sstevel@tonic-gate 	buffer_consume_end(&incoming_packet, padlen);
11010Sstevel@tonic-gate 
11020Sstevel@tonic-gate 	DBG(debug("input: len before de-compress %d", buffer_len(&incoming_packet)));
11030Sstevel@tonic-gate 	if (comp && comp->enabled) {
11040Sstevel@tonic-gate 		buffer_clear(&compression_buffer);
11050Sstevel@tonic-gate 		buffer_uncompress(&incoming_packet, &compression_buffer);
11060Sstevel@tonic-gate 		buffer_clear(&incoming_packet);
11070Sstevel@tonic-gate 		buffer_append(&incoming_packet, buffer_ptr(&compression_buffer),
11080Sstevel@tonic-gate 		    buffer_len(&compression_buffer));
11090Sstevel@tonic-gate 		DBG(debug("input: len after de-compress %d",
11100Sstevel@tonic-gate 		    buffer_len(&incoming_packet)));
11110Sstevel@tonic-gate 	}
11120Sstevel@tonic-gate 	/*
11130Sstevel@tonic-gate 	 * get packet type, implies consume.
11140Sstevel@tonic-gate 	 * return length of payload (without type field)
11150Sstevel@tonic-gate 	 */
11160Sstevel@tonic-gate 	type = buffer_get_char(&incoming_packet);
11170Sstevel@tonic-gate #ifdef ALTPRIVSEP
11180Sstevel@tonic-gate 	if (type == SSH2_MSG_NEWKEYS)
11190Sstevel@tonic-gate 		/* set_newkeys(MODE_OUT) in client, server, but not monitor */
11200Sstevel@tonic-gate 		if (!packet_is_server() && !packet_is_monitor())
11210Sstevel@tonic-gate 			set_newkeys(MODE_IN);
11220Sstevel@tonic-gate #else /* ALTPRIVSEP */
11230Sstevel@tonic-gate 	if (type == SSH2_MSG_NEWKEYS)
11240Sstevel@tonic-gate 		set_newkeys(MODE_IN);
11250Sstevel@tonic-gate #endif /* ALTPRIVSEP */
11260Sstevel@tonic-gate #ifdef PACKET_DEBUG
11270Sstevel@tonic-gate 	fprintf(stderr, "read/plain[%d]:\r\n", type);
11280Sstevel@tonic-gate 	buffer_dump(&incoming_packet);
11290Sstevel@tonic-gate #endif
11300Sstevel@tonic-gate 	/* reset for next packet */
11310Sstevel@tonic-gate 	packet_length = 0;
11320Sstevel@tonic-gate 	return type;
11330Sstevel@tonic-gate }
11340Sstevel@tonic-gate 
11350Sstevel@tonic-gate int
11360Sstevel@tonic-gate packet_read_poll_seqnr(u_int32_t *seqnr_p)
11370Sstevel@tonic-gate {
11380Sstevel@tonic-gate 	u_int reason, seqnr;
11390Sstevel@tonic-gate 	u_char type;
11400Sstevel@tonic-gate 	char *msg;
11410Sstevel@tonic-gate 
11420Sstevel@tonic-gate 	for (;;) {
11430Sstevel@tonic-gate 		if (compat20) {
11440Sstevel@tonic-gate 			type = packet_read_poll2(seqnr_p);
11450Sstevel@tonic-gate 			DBG(debug("received packet type %d", type));
11460Sstevel@tonic-gate 			switch (type) {
11470Sstevel@tonic-gate 			case SSH2_MSG_IGNORE:
11480Sstevel@tonic-gate 				break;
11490Sstevel@tonic-gate 			case SSH2_MSG_DEBUG:
11500Sstevel@tonic-gate 				packet_get_char();
11510Sstevel@tonic-gate 				msg = packet_get_string(NULL);
11520Sstevel@tonic-gate 				debug("Remote: %.900s", msg);
11530Sstevel@tonic-gate 				xfree(msg);
11540Sstevel@tonic-gate 				msg = packet_get_string(NULL);
11550Sstevel@tonic-gate 				xfree(msg);
11560Sstevel@tonic-gate 				break;
11570Sstevel@tonic-gate 			case SSH2_MSG_DISCONNECT:
11580Sstevel@tonic-gate 				reason = packet_get_int();
11590Sstevel@tonic-gate 				msg = packet_get_string(NULL);
11600Sstevel@tonic-gate 				log("Received disconnect from %s: %u: %.400s",
11610Sstevel@tonic-gate 				    get_remote_ipaddr(), reason, msg);
11620Sstevel@tonic-gate 				xfree(msg);
11630Sstevel@tonic-gate 				fatal_cleanup();
11640Sstevel@tonic-gate 				break;
11650Sstevel@tonic-gate 			case SSH2_MSG_UNIMPLEMENTED:
11660Sstevel@tonic-gate 				seqnr = packet_get_int();
11670Sstevel@tonic-gate 				debug("Received SSH2_MSG_UNIMPLEMENTED for %u",
11680Sstevel@tonic-gate 				    seqnr);
11690Sstevel@tonic-gate 				break;
11700Sstevel@tonic-gate 			default:
11710Sstevel@tonic-gate 				return type;
11720Sstevel@tonic-gate 				break;
11730Sstevel@tonic-gate 			}
11740Sstevel@tonic-gate 		} else {
11750Sstevel@tonic-gate 			type = packet_read_poll1();
11760Sstevel@tonic-gate 			DBG(debug("received packet type %d", type));
11770Sstevel@tonic-gate 			switch (type) {
11780Sstevel@tonic-gate 			case SSH_MSG_IGNORE:
11790Sstevel@tonic-gate 				break;
11800Sstevel@tonic-gate 			case SSH_MSG_DEBUG:
11810Sstevel@tonic-gate 				msg = packet_get_string(NULL);
11820Sstevel@tonic-gate 				debug("Remote: %.900s", msg);
11830Sstevel@tonic-gate 				xfree(msg);
11840Sstevel@tonic-gate 				break;
11850Sstevel@tonic-gate 			case SSH_MSG_DISCONNECT:
11860Sstevel@tonic-gate 				msg = packet_get_string(NULL);
11870Sstevel@tonic-gate 				log("Received disconnect from %s: %.400s",
11880Sstevel@tonic-gate 				    get_remote_ipaddr(), msg);
11890Sstevel@tonic-gate 				fatal_cleanup();
11900Sstevel@tonic-gate 				xfree(msg);
11910Sstevel@tonic-gate 				break;
11920Sstevel@tonic-gate 			default:
11930Sstevel@tonic-gate 				return type;
11940Sstevel@tonic-gate 				break;
11950Sstevel@tonic-gate 			}
11960Sstevel@tonic-gate 		}
11970Sstevel@tonic-gate 	}
11980Sstevel@tonic-gate }
11990Sstevel@tonic-gate 
12000Sstevel@tonic-gate int
12010Sstevel@tonic-gate packet_read_poll(void)
12020Sstevel@tonic-gate {
12030Sstevel@tonic-gate 	return packet_read_poll_seqnr(NULL);
12040Sstevel@tonic-gate }
12050Sstevel@tonic-gate 
12060Sstevel@tonic-gate /*
12070Sstevel@tonic-gate  * Buffers the given amount of input characters.  This is intended to be used
12080Sstevel@tonic-gate  * together with packet_read_poll.
12090Sstevel@tonic-gate  */
12100Sstevel@tonic-gate 
12110Sstevel@tonic-gate void
12120Sstevel@tonic-gate packet_process_incoming(const char *buf, u_int len)
12130Sstevel@tonic-gate {
12140Sstevel@tonic-gate 	buffer_append(&input, buf, len);
12150Sstevel@tonic-gate }
12160Sstevel@tonic-gate 
12170Sstevel@tonic-gate /* Returns a character from the packet. */
12180Sstevel@tonic-gate 
12190Sstevel@tonic-gate u_int
12200Sstevel@tonic-gate packet_get_char(void)
12210Sstevel@tonic-gate {
12220Sstevel@tonic-gate 	char ch;
12230Sstevel@tonic-gate 
12240Sstevel@tonic-gate 	buffer_get(&incoming_packet, &ch, 1);
12250Sstevel@tonic-gate 	return (u_char) ch;
12260Sstevel@tonic-gate }
12270Sstevel@tonic-gate 
12280Sstevel@tonic-gate /* Returns an integer from the packet data. */
12290Sstevel@tonic-gate 
12300Sstevel@tonic-gate u_int
12310Sstevel@tonic-gate packet_get_int(void)
12320Sstevel@tonic-gate {
12330Sstevel@tonic-gate 	return buffer_get_int(&incoming_packet);
12340Sstevel@tonic-gate }
12350Sstevel@tonic-gate 
12360Sstevel@tonic-gate /*
12370Sstevel@tonic-gate  * Returns an arbitrary precision integer from the packet data.  The integer
12380Sstevel@tonic-gate  * must have been initialized before this call.
12390Sstevel@tonic-gate  */
12400Sstevel@tonic-gate 
12410Sstevel@tonic-gate void
12420Sstevel@tonic-gate packet_get_bignum(BIGNUM * value)
12430Sstevel@tonic-gate {
12440Sstevel@tonic-gate 	buffer_get_bignum(&incoming_packet, value);
12450Sstevel@tonic-gate }
12460Sstevel@tonic-gate 
12470Sstevel@tonic-gate void
12480Sstevel@tonic-gate packet_get_bignum2(BIGNUM * value)
12490Sstevel@tonic-gate {
12500Sstevel@tonic-gate 	buffer_get_bignum2(&incoming_packet, value);
12510Sstevel@tonic-gate }
12520Sstevel@tonic-gate 
12530Sstevel@tonic-gate void *
12540Sstevel@tonic-gate packet_get_raw(u_int *length_ptr)
12550Sstevel@tonic-gate {
12560Sstevel@tonic-gate 	u_int bytes = buffer_len(&incoming_packet);
12570Sstevel@tonic-gate 
12580Sstevel@tonic-gate 	if (length_ptr != NULL)
12590Sstevel@tonic-gate 		*length_ptr = bytes;
12600Sstevel@tonic-gate 	return buffer_ptr(&incoming_packet);
12610Sstevel@tonic-gate }
12620Sstevel@tonic-gate 
12630Sstevel@tonic-gate int
12640Sstevel@tonic-gate packet_remaining(void)
12650Sstevel@tonic-gate {
12660Sstevel@tonic-gate 	return buffer_len(&incoming_packet);
12670Sstevel@tonic-gate }
12680Sstevel@tonic-gate 
12690Sstevel@tonic-gate /*
12700Sstevel@tonic-gate  * Returns a string from the packet data.  The string is allocated using
12710Sstevel@tonic-gate  * xmalloc; it is the responsibility of the calling program to free it when
12720Sstevel@tonic-gate  * no longer needed.  The length_ptr argument may be NULL, or point to an
12730Sstevel@tonic-gate  * integer into which the length of the string is stored.
12740Sstevel@tonic-gate  */
12750Sstevel@tonic-gate 
12760Sstevel@tonic-gate void *
12770Sstevel@tonic-gate packet_get_string(u_int *length_ptr)
12780Sstevel@tonic-gate {
12790Sstevel@tonic-gate 	return buffer_get_string(&incoming_packet, length_ptr);
12800Sstevel@tonic-gate }
12810Sstevel@tonic-gate char *
12820Sstevel@tonic-gate packet_get_ascii_cstring()
12830Sstevel@tonic-gate {
12840Sstevel@tonic-gate 	return buffer_get_ascii_cstring(&incoming_packet);
12850Sstevel@tonic-gate }
12860Sstevel@tonic-gate u_char *
12870Sstevel@tonic-gate packet_get_utf8_cstring()
12880Sstevel@tonic-gate {
12890Sstevel@tonic-gate 	return buffer_get_utf8_cstring(&incoming_packet);
12900Sstevel@tonic-gate }
12910Sstevel@tonic-gate 
12920Sstevel@tonic-gate /*
12930Sstevel@tonic-gate  * Sends a diagnostic message from the server to the client.  This message
12940Sstevel@tonic-gate  * can be sent at any time (but not while constructing another message). The
12950Sstevel@tonic-gate  * message is printed immediately, but only if the client is being executed
12960Sstevel@tonic-gate  * in verbose mode.  These messages are primarily intended to ease debugging
12970Sstevel@tonic-gate  * authentication problems.   The length of the formatted message must not
12980Sstevel@tonic-gate  * exceed 1024 bytes.  This will automatically call packet_write_wait.
12990Sstevel@tonic-gate  */
13000Sstevel@tonic-gate 
13010Sstevel@tonic-gate void
13020Sstevel@tonic-gate packet_send_debug(const char *fmt,...)
13030Sstevel@tonic-gate {
13040Sstevel@tonic-gate 	char buf[1024];
13050Sstevel@tonic-gate 	va_list args;
13060Sstevel@tonic-gate 
13070Sstevel@tonic-gate 	if (compat20 && (datafellows & SSH_BUG_DEBUG))
13080Sstevel@tonic-gate 		return;
13090Sstevel@tonic-gate 
13100Sstevel@tonic-gate 	va_start(args, fmt);
13110Sstevel@tonic-gate 	vsnprintf(buf, sizeof(buf), gettext(fmt), args);
13120Sstevel@tonic-gate 	va_end(args);
13130Sstevel@tonic-gate 
13140Sstevel@tonic-gate #ifdef ALTPRIVSEP
13150Sstevel@tonic-gate 	/* shouldn't happen */
13160Sstevel@tonic-gate 	if (packet_monitor) {
13170Sstevel@tonic-gate 		debug("packet_send_debug: %s", buf);
13180Sstevel@tonic-gate 		return;
13190Sstevel@tonic-gate 	}
13200Sstevel@tonic-gate #endif /* ALTPRIVSEP */
13210Sstevel@tonic-gate 
13220Sstevel@tonic-gate 	if (compat20) {
13230Sstevel@tonic-gate 		packet_start(SSH2_MSG_DEBUG);
13240Sstevel@tonic-gate 		packet_put_char(0);	/* bool: always display */
13250Sstevel@tonic-gate 		packet_put_cstring(buf);
13260Sstevel@tonic-gate 		packet_put_cstring("");
13270Sstevel@tonic-gate 	} else {
13280Sstevel@tonic-gate 		packet_start(SSH_MSG_DEBUG);
13290Sstevel@tonic-gate 		packet_put_cstring(buf);
13300Sstevel@tonic-gate 	}
13310Sstevel@tonic-gate 	packet_send();
13320Sstevel@tonic-gate 	packet_write_wait();
13330Sstevel@tonic-gate }
13340Sstevel@tonic-gate 
13350Sstevel@tonic-gate /*
13360Sstevel@tonic-gate  * Logs the error plus constructs and sends a disconnect packet, closes the
13370Sstevel@tonic-gate  * connection, and exits.  This function never returns. The error message
13380Sstevel@tonic-gate  * should not contain a newline.  The length of the formatted message must
13390Sstevel@tonic-gate  * not exceed 1024 bytes.
13400Sstevel@tonic-gate  */
13410Sstevel@tonic-gate 
13420Sstevel@tonic-gate void
13430Sstevel@tonic-gate packet_disconnect(const char *fmt,...)
13440Sstevel@tonic-gate {
13450Sstevel@tonic-gate 	char buf[1024];
13460Sstevel@tonic-gate 	va_list args;
13470Sstevel@tonic-gate 	static int disconnecting = 0;
13480Sstevel@tonic-gate 
13490Sstevel@tonic-gate 	if (disconnecting)	/* Guard against recursive invocations. */
13500Sstevel@tonic-gate 		fatal("packet_disconnect called recursively.");
13510Sstevel@tonic-gate 	disconnecting = 1;
13520Sstevel@tonic-gate 
13530Sstevel@tonic-gate 	/*
13540Sstevel@tonic-gate 	 * Format the message.  Note that the caller must make sure the
13550Sstevel@tonic-gate 	 * message is of limited size.
13560Sstevel@tonic-gate 	 */
13570Sstevel@tonic-gate 	va_start(args, fmt);
13580Sstevel@tonic-gate 	vsnprintf(buf, sizeof(buf), fmt, args);
13590Sstevel@tonic-gate 	va_end(args);
13600Sstevel@tonic-gate 
13610Sstevel@tonic-gate #ifdef ALTPRIVSEP
13620Sstevel@tonic-gate 	/*
13630Sstevel@tonic-gate 	 * If we packet_disconnect() in the monitor the fatal cleanups will take
13640Sstevel@tonic-gate 	 * care of the child.  See main() in sshd.c.  We don't send the packet
13650Sstevel@tonic-gate 	 * disconnect message here because: a) the child might not be looking
13660Sstevel@tonic-gate 	 * for it and b) because we don't really know if the child is compat20
13670Sstevel@tonic-gate 	 * or not as we lost that information when packet_set_monitor() was
13680Sstevel@tonic-gate 	 * called.
13690Sstevel@tonic-gate 	 */
13700Sstevel@tonic-gate 	if (packet_monitor)
13710Sstevel@tonic-gate 		goto close_stuff;
13720Sstevel@tonic-gate #endif /* ALTPRIVSEP */
13730Sstevel@tonic-gate 
13740Sstevel@tonic-gate 	/* Send the disconnect message to the other side, and wait for it to get sent. */
13750Sstevel@tonic-gate 	if (compat20) {
13760Sstevel@tonic-gate 		packet_start(SSH2_MSG_DISCONNECT);
13770Sstevel@tonic-gate 		packet_put_int(SSH2_DISCONNECT_PROTOCOL_ERROR);
13780Sstevel@tonic-gate 		packet_put_cstring(buf);
13790Sstevel@tonic-gate 		packet_put_cstring("");
13800Sstevel@tonic-gate 	} else {
13810Sstevel@tonic-gate 		packet_start(SSH_MSG_DISCONNECT);
13820Sstevel@tonic-gate 		packet_put_cstring(buf);
13830Sstevel@tonic-gate 	}
13840Sstevel@tonic-gate 	packet_send();
13850Sstevel@tonic-gate 	packet_write_wait();
13860Sstevel@tonic-gate 
13870Sstevel@tonic-gate #ifdef ALTPRIVSEP
13880Sstevel@tonic-gate close_stuff:
13890Sstevel@tonic-gate #endif /* ALTPRIVSEP */
13900Sstevel@tonic-gate 	/* Stop listening for connections. */
13910Sstevel@tonic-gate 	channel_close_all();
13920Sstevel@tonic-gate 
13930Sstevel@tonic-gate 	/* Close the connection. */
13940Sstevel@tonic-gate 	packet_close();
13950Sstevel@tonic-gate 
13960Sstevel@tonic-gate 	/* Display the error locally and exit. */
13970Sstevel@tonic-gate 	log("Disconnecting: %.100s", buf);
13980Sstevel@tonic-gate 	fatal_cleanup();
13990Sstevel@tonic-gate }
14000Sstevel@tonic-gate 
14010Sstevel@tonic-gate /* Checks if there is any buffered output, and tries to write some of the output. */
14020Sstevel@tonic-gate 
14030Sstevel@tonic-gate void
14040Sstevel@tonic-gate packet_write_poll(void)
14050Sstevel@tonic-gate {
14060Sstevel@tonic-gate 	int len = buffer_len(&output);
14070Sstevel@tonic-gate 
14080Sstevel@tonic-gate 	if (len > 0) {
14090Sstevel@tonic-gate 		len = write(connection_out, buffer_ptr(&output), len);
14100Sstevel@tonic-gate 		if (len <= 0) {
14110Sstevel@tonic-gate 			if (errno == EAGAIN)
14120Sstevel@tonic-gate 				return;
14130Sstevel@tonic-gate 			else
14140Sstevel@tonic-gate 				fatal("Write failed: %.100s", strerror(errno));
14150Sstevel@tonic-gate 		}
14160Sstevel@tonic-gate 		buffer_consume(&output, len);
14170Sstevel@tonic-gate 	}
14180Sstevel@tonic-gate }
14190Sstevel@tonic-gate 
14200Sstevel@tonic-gate /*
14210Sstevel@tonic-gate  * Calls packet_write_poll repeatedly until all pending output data has been
14220Sstevel@tonic-gate  * written.
14230Sstevel@tonic-gate  */
14240Sstevel@tonic-gate 
14250Sstevel@tonic-gate void
14260Sstevel@tonic-gate packet_write_wait(void)
14270Sstevel@tonic-gate {
14280Sstevel@tonic-gate 	fd_set *setp;
14290Sstevel@tonic-gate 
14300Sstevel@tonic-gate 	setp = (fd_set *)xmalloc(howmany(connection_out + 1, NFDBITS) *
14310Sstevel@tonic-gate 	    sizeof(fd_mask));
14320Sstevel@tonic-gate 	packet_write_poll();
14330Sstevel@tonic-gate 	while (packet_have_data_to_write()) {
14340Sstevel@tonic-gate 		memset(setp, 0, howmany(connection_out + 1, NFDBITS) *
14350Sstevel@tonic-gate 		    sizeof(fd_mask));
14360Sstevel@tonic-gate 		FD_SET(connection_out, setp);
14370Sstevel@tonic-gate 		while (select(connection_out + 1, NULL, setp, NULL, NULL) == -1 &&
14380Sstevel@tonic-gate 		    (errno == EAGAIN || errno == EINTR))
14390Sstevel@tonic-gate 			;
14400Sstevel@tonic-gate 		packet_write_poll();
14410Sstevel@tonic-gate 	}
14420Sstevel@tonic-gate 	xfree(setp);
14430Sstevel@tonic-gate }
14440Sstevel@tonic-gate 
14450Sstevel@tonic-gate /* Returns true if there is buffered data to write to the connection. */
14460Sstevel@tonic-gate 
14470Sstevel@tonic-gate int
14480Sstevel@tonic-gate packet_have_data_to_write(void)
14490Sstevel@tonic-gate {
14500Sstevel@tonic-gate 	return buffer_len(&output) != 0;
14510Sstevel@tonic-gate }
14520Sstevel@tonic-gate 
14530Sstevel@tonic-gate /* Returns true if there is not too much data to write to the connection. */
14540Sstevel@tonic-gate 
14550Sstevel@tonic-gate int
14560Sstevel@tonic-gate packet_not_very_much_data_to_write(void)
14570Sstevel@tonic-gate {
14580Sstevel@tonic-gate 	if (interactive_mode)
14590Sstevel@tonic-gate 		return buffer_len(&output) < 16384;
14600Sstevel@tonic-gate 	else
14610Sstevel@tonic-gate 		return buffer_len(&output) < 128 * 1024;
14620Sstevel@tonic-gate }
14630Sstevel@tonic-gate 
14640Sstevel@tonic-gate /* Informs that the current session is interactive.  Sets IP flags for that. */
14650Sstevel@tonic-gate 
14660Sstevel@tonic-gate void
14670Sstevel@tonic-gate packet_set_interactive(int interactive)
14680Sstevel@tonic-gate {
14690Sstevel@tonic-gate 	static int called = 0;
14700Sstevel@tonic-gate #if defined(IP_TOS) && !defined(IP_TOS_IS_BROKEN)
14710Sstevel@tonic-gate 	int lowdelay = IPTOS_LOWDELAY;
14720Sstevel@tonic-gate 	int throughput = IPTOS_THROUGHPUT;
14730Sstevel@tonic-gate #endif
14740Sstevel@tonic-gate 
14750Sstevel@tonic-gate 	if (called)
14760Sstevel@tonic-gate 		return;
14770Sstevel@tonic-gate 	called = 1;
14780Sstevel@tonic-gate 
14790Sstevel@tonic-gate 	/* Record that we are in interactive mode. */
14800Sstevel@tonic-gate 	interactive_mode = interactive;
14810Sstevel@tonic-gate 
14820Sstevel@tonic-gate 	/* Only set socket options if using a socket.  */
14830Sstevel@tonic-gate 	if (!packet_connection_is_on_socket())
14840Sstevel@tonic-gate 		return;
14850Sstevel@tonic-gate 	/*
14860Sstevel@tonic-gate 	 * IPTOS_LOWDELAY and IPTOS_THROUGHPUT are IPv4 only
14870Sstevel@tonic-gate 	 */
14880Sstevel@tonic-gate 	if (interactive) {
14890Sstevel@tonic-gate 		/*
14900Sstevel@tonic-gate 		 * Set IP options for an interactive connection.  Use
14910Sstevel@tonic-gate 		 * IPTOS_LOWDELAY and TCP_NODELAY.
14920Sstevel@tonic-gate 		 */
14930Sstevel@tonic-gate #if defined(IP_TOS) && !defined(IP_TOS_IS_BROKEN)
14940Sstevel@tonic-gate 		if (packet_connection_is_ipv4()) {
14950Sstevel@tonic-gate 			if (setsockopt(connection_in, IPPROTO_IP, IP_TOS,
14960Sstevel@tonic-gate 			    &lowdelay, sizeof(lowdelay)) < 0)
14970Sstevel@tonic-gate 				error("setsockopt IPTOS_LOWDELAY: %.100s",
14980Sstevel@tonic-gate 				    strerror(errno));
14990Sstevel@tonic-gate 		}
15000Sstevel@tonic-gate #endif
15010Sstevel@tonic-gate 		set_nodelay(connection_in);
15020Sstevel@tonic-gate 	}
15030Sstevel@tonic-gate #if defined(IP_TOS) && !defined(IP_TOS_IS_BROKEN)
15040Sstevel@tonic-gate 	else if (packet_connection_is_ipv4()) {
15050Sstevel@tonic-gate 		/*
15060Sstevel@tonic-gate 		 * Set IP options for a non-interactive connection.  Use
15070Sstevel@tonic-gate 		 * IPTOS_THROUGHPUT.
15080Sstevel@tonic-gate 		 */
15090Sstevel@tonic-gate 		if (setsockopt(connection_in, IPPROTO_IP, IP_TOS, &throughput,
15100Sstevel@tonic-gate 		    sizeof(throughput)) < 0)
15110Sstevel@tonic-gate 			error("setsockopt IPTOS_THROUGHPUT: %.100s", strerror(errno));
15120Sstevel@tonic-gate 	}
15130Sstevel@tonic-gate #endif
15140Sstevel@tonic-gate }
15150Sstevel@tonic-gate 
15160Sstevel@tonic-gate /* Returns true if the current connection is interactive. */
15170Sstevel@tonic-gate 
15180Sstevel@tonic-gate int
15190Sstevel@tonic-gate packet_is_interactive(void)
15200Sstevel@tonic-gate {
15210Sstevel@tonic-gate 	return interactive_mode;
15220Sstevel@tonic-gate }
15230Sstevel@tonic-gate 
15240Sstevel@tonic-gate int
15250Sstevel@tonic-gate packet_set_maxsize(int s)
15260Sstevel@tonic-gate {
15270Sstevel@tonic-gate 	static int called = 0;
15280Sstevel@tonic-gate 
15290Sstevel@tonic-gate 	if (called) {
15300Sstevel@tonic-gate 		log("packet_set_maxsize: called twice: old %d new %d",
15310Sstevel@tonic-gate 		    max_packet_size, s);
15320Sstevel@tonic-gate 		return -1;
15330Sstevel@tonic-gate 	}
15340Sstevel@tonic-gate 	if (s < 4 * 1024 || s > 1024 * 1024) {
15350Sstevel@tonic-gate 		log("packet_set_maxsize: bad size %d", s);
15360Sstevel@tonic-gate 		return -1;
15370Sstevel@tonic-gate 	}
15380Sstevel@tonic-gate 	called = 1;
15390Sstevel@tonic-gate 	debug("packet_set_maxsize: setting to %d", s);
15400Sstevel@tonic-gate 	max_packet_size = s;
15410Sstevel@tonic-gate 	return s;
15420Sstevel@tonic-gate }
15430Sstevel@tonic-gate 
15440Sstevel@tonic-gate /* roundup current message to pad bytes */
15450Sstevel@tonic-gate void
15460Sstevel@tonic-gate packet_add_padding(u_char pad)
15470Sstevel@tonic-gate {
15480Sstevel@tonic-gate 	extra_pad = pad;
15490Sstevel@tonic-gate }
15500Sstevel@tonic-gate 
15510Sstevel@tonic-gate /*
15520Sstevel@tonic-gate  * 9.2.  Ignored Data Message
15530Sstevel@tonic-gate  *
15540Sstevel@tonic-gate  *   byte      SSH_MSG_IGNORE
15550Sstevel@tonic-gate  *   string    data
15560Sstevel@tonic-gate  *
15570Sstevel@tonic-gate  * All implementations MUST understand (and ignore) this message at any
15580Sstevel@tonic-gate  * time (after receiving the protocol version). No implementation is
15590Sstevel@tonic-gate  * required to send them. This message can be used as an additional
15600Sstevel@tonic-gate  * protection measure against advanced traffic analysis techniques.
15610Sstevel@tonic-gate  */
15620Sstevel@tonic-gate void
15630Sstevel@tonic-gate packet_send_ignore(int nbytes)
15640Sstevel@tonic-gate {
1565*5562Sjp161948 	u_int32_t rnd = 0;
15660Sstevel@tonic-gate 	int i;
15670Sstevel@tonic-gate 
15680Sstevel@tonic-gate #ifdef ALTPRIVSEP
15690Sstevel@tonic-gate 	/* shouldn't happen -- see packet_set_monitor() */
15700Sstevel@tonic-gate 	if (packet_monitor)
15710Sstevel@tonic-gate 		return;
15720Sstevel@tonic-gate #endif /* ALTPRIVSEP */
15730Sstevel@tonic-gate 
15740Sstevel@tonic-gate 	packet_start(compat20 ? SSH2_MSG_IGNORE : SSH_MSG_IGNORE);
15750Sstevel@tonic-gate 	packet_put_int(nbytes);
15760Sstevel@tonic-gate 	for (i = 0; i < nbytes; i++) {
15770Sstevel@tonic-gate 		if (i % 4 == 0)
1578*5562Sjp161948 			rnd = arc4random();
1579*5562Sjp161948 		packet_put_char((u_char)rnd & 0xff);
1580*5562Sjp161948 		rnd >>= 8;
15810Sstevel@tonic-gate 	}
15820Sstevel@tonic-gate }
15830Sstevel@tonic-gate 
1584*5562Sjp161948 #define MAX_PACKETS	(1U<<31)
1585*5562Sjp161948 int
1586*5562Sjp161948 packet_need_rekeying(void)
1587*5562Sjp161948 {
1588*5562Sjp161948 	if (datafellows & SSH_BUG_NOREKEY)
1589*5562Sjp161948 		return 0;
1590*5562Sjp161948 	return
1591*5562Sjp161948 	    (p_send.packets > MAX_PACKETS) ||
1592*5562Sjp161948 	    (p_read.packets > MAX_PACKETS) ||
1593*5562Sjp161948 	    (max_blocks_out && (p_send.blocks > max_blocks_out)) ||
1594*5562Sjp161948 	    (max_blocks_in  && (p_read.blocks > max_blocks_in));
1595*5562Sjp161948 }
1596*5562Sjp161948 
1597*5562Sjp161948 void
1598*5562Sjp161948 packet_set_rekey_limit(u_int32_t bytes)
1599*5562Sjp161948 {
1600*5562Sjp161948 	rekey_limit = bytes;
1601*5562Sjp161948 }
1602*5562Sjp161948 
16030Sstevel@tonic-gate #ifdef ALTPRIVSEP
16040Sstevel@tonic-gate void
16050Sstevel@tonic-gate packet_set_server(void)
16060Sstevel@tonic-gate {
16070Sstevel@tonic-gate 	packet_server = 1;
16080Sstevel@tonic-gate }
16090Sstevel@tonic-gate 
16100Sstevel@tonic-gate void
16110Sstevel@tonic-gate packet_set_no_monitor(void)
16120Sstevel@tonic-gate {
16130Sstevel@tonic-gate 	packet_server = 0;
16140Sstevel@tonic-gate }
16150Sstevel@tonic-gate 
16160Sstevel@tonic-gate int
16170Sstevel@tonic-gate packet_is_server(void)
16180Sstevel@tonic-gate {
16190Sstevel@tonic-gate 	return (packet_server);
16200Sstevel@tonic-gate }
16210Sstevel@tonic-gate 
16220Sstevel@tonic-gate void
16230Sstevel@tonic-gate packet_set_monitor(int pipe)
16240Sstevel@tonic-gate {
16250Sstevel@tonic-gate 	int dup_fd;
16260Sstevel@tonic-gate 
16270Sstevel@tonic-gate 	packet_server = 1;
16280Sstevel@tonic-gate 	packet_monitor = 1;
16290Sstevel@tonic-gate 
16300Sstevel@tonic-gate 	/*
16310Sstevel@tonic-gate 	 * Awful hack follows.
16320Sstevel@tonic-gate 	 *
16330Sstevel@tonic-gate 	 * For SSHv1 the monitor does not process any SSHv1 packets, only
16340Sstevel@tonic-gate 	 * ALTPRIVSEP packets.  We take advantage of that here to keep changes
16350Sstevel@tonic-gate 	 * to packet.c to a minimum by using the SSHv2 binary packet protocol,
16360Sstevel@tonic-gate 	 * with cipher "none," mac "none" and compression alg "none," as the
16370Sstevel@tonic-gate 	 * basis for the monitor protocol.  And so to force packet.c to treat
16380Sstevel@tonic-gate 	 * packets as SSHv2 we force compat20 == 1 here.
16390Sstevel@tonic-gate 	 *
16400Sstevel@tonic-gate 	 * For completeness and to help future developers catch this we also
16410Sstevel@tonic-gate 	 * force compat20 == 1 in the monitor loop, in serverloop.c.
16420Sstevel@tonic-gate 	 */
16430Sstevel@tonic-gate 	compat20 = 1;
16440Sstevel@tonic-gate 
16450Sstevel@tonic-gate 	/*
16460Sstevel@tonic-gate 	 * NOTE:  Assumptions below!
16470Sstevel@tonic-gate 	 *
16480Sstevel@tonic-gate 	 *  - lots of packet.c code assumes that (connection_in ==
16490Sstevel@tonic-gate 	 *  connection_out) -> connection is socket
16500Sstevel@tonic-gate 	 *
16510Sstevel@tonic-gate 	 *  - packet_close() does not shutdown() the connection fildes
16520Sstevel@tonic-gate 	 *  if connection_in != connection_out
16530Sstevel@tonic-gate 	 *
16540Sstevel@tonic-gate 	 *  - other code assumes the connection is a socket if
16550Sstevel@tonic-gate 	 *  connection_in == connection_out
16560Sstevel@tonic-gate 	 */
16570Sstevel@tonic-gate 
16580Sstevel@tonic-gate 	if ((dup_fd = dup(pipe)) < 0)
16590Sstevel@tonic-gate 		fatal("Monitor failed to start: %s", strerror(errno));
16600Sstevel@tonic-gate 
16610Sstevel@tonic-gate 	/*
16620Sstevel@tonic-gate 	 * make sure that the monitor's child's socket is not shutdown(3SOCKET)
16630Sstevel@tonic-gate 	 * when we packet_close()
16640Sstevel@tonic-gate 	 */
16650Sstevel@tonic-gate 	if (packet_connection_is_on_socket())
16660Sstevel@tonic-gate 		connection_out = -1;
16670Sstevel@tonic-gate 
16680Sstevel@tonic-gate 	/* now cleanup state related to ssh socket */
16690Sstevel@tonic-gate 	packet_close();
16700Sstevel@tonic-gate 
16710Sstevel@tonic-gate 	/* now make the monitor pipe look like the ssh connection */
16720Sstevel@tonic-gate 	packet_set_connection(pipe, dup_fd);
16730Sstevel@tonic-gate }
16740Sstevel@tonic-gate 
16750Sstevel@tonic-gate int
16760Sstevel@tonic-gate packet_is_monitor(void)
16770Sstevel@tonic-gate {
16780Sstevel@tonic-gate 	return (packet_monitor);
16790Sstevel@tonic-gate }
16800Sstevel@tonic-gate #endif /* ALTPRIVSEP */
1681