packet.c revision 224638
1221420Sdes/* $OpenBSD: packet.c,v 1.172 2010/11/13 23:27:50 djm Exp $ */
2224638Sbrooks/* $FreeBSD$ */
357429Smarkm/*
457429Smarkm * Author: Tatu Ylonen <ylo@cs.hut.fi>
557429Smarkm * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
657429Smarkm *                    All rights reserved
757429Smarkm * This file contains code implementing the packet protocol and communication
857429Smarkm * with the other side.  This same code is used both on client and server side.
960573Skris *
1065668Skris * As far as I am concerned, the code I have written for this software
1165668Skris * can be used freely for any purpose.  Any derived versions of this
1265668Skris * software must be clearly marked as such, and if the derived work is
1365668Skris * incompatible with the protocol description in the RFC file, it must be
1465668Skris * called by a name other than "ssh" or "Secure Shell".
1565668Skris *
1665668Skris *
1760573Skris * SSH2 packet format added by Markus Friedl.
1892555Sdes * Copyright (c) 2000, 2001 Markus Friedl.  All rights reserved.
1960573Skris *
2065668Skris * Redistribution and use in source and binary forms, with or without
2165668Skris * modification, are permitted provided that the following conditions
2265668Skris * are met:
2365668Skris * 1. Redistributions of source code must retain the above copyright
2465668Skris *    notice, this list of conditions and the following disclaimer.
2565668Skris * 2. Redistributions in binary form must reproduce the above copyright
2665668Skris *    notice, this list of conditions and the following disclaimer in the
2765668Skris *    documentation and/or other materials provided with the distribution.
2865668Skris *
2965668Skris * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
3065668Skris * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
3165668Skris * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
3265668Skris * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
3365668Skris * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
3465668Skris * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
3565668Skris * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
3665668Skris * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
3765668Skris * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
3865668Skris * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3957429Smarkm */
4057429Smarkm
4157429Smarkm#include "includes.h"
42162852Sdes
43162852Sdes#include <sys/types.h>
44124208Sdes#include "openbsd-compat/sys-queue.h"
45162852Sdes#include <sys/param.h>
46162852Sdes#include <sys/socket.h>
47162852Sdes#ifdef HAVE_SYS_TIME_H
48162852Sdes# include <sys/time.h>
49162852Sdes#endif
50124208Sdes
51162852Sdes#include <netinet/in.h>
52162852Sdes#include <netinet/ip.h>
53162852Sdes#include <arpa/inet.h>
54162852Sdes
55162852Sdes#include <errno.h>
56162852Sdes#include <stdarg.h>
57162852Sdes#include <stdio.h>
58162852Sdes#include <stdlib.h>
59162852Sdes#include <string.h>
60162852Sdes#include <unistd.h>
61162852Sdes#include <signal.h>
62162852Sdes
6357429Smarkm#include "xmalloc.h"
6457429Smarkm#include "buffer.h"
6557429Smarkm#include "packet.h"
6657429Smarkm#include "crc32.h"
6757429Smarkm#include "compress.h"
6857429Smarkm#include "deattack.h"
6960573Skris#include "channels.h"
7060573Skris#include "compat.h"
7176259Sgreen#include "ssh1.h"
7260573Skris#include "ssh2.h"
7369587Sgreen#include "cipher.h"
74162852Sdes#include "key.h"
7560573Skris#include "kex.h"
7676259Sgreen#include "mac.h"
7776259Sgreen#include "log.h"
7876259Sgreen#include "canohost.h"
7992555Sdes#include "misc.h"
8098675Sdes#include "ssh.h"
81197679Sdes#include "roaming.h"
8260573Skris
8360573Skris#ifdef PACKET_DEBUG
8460573Skris#define DBG(x) x
8560573Skris#else
8660573Skris#define DBG(x)
8760573Skris#endif
8860573Skris
89192595Sdes#define PACKET_MAX_SIZE (256 * 1024)
90192595Sdes
91197679Sdesstruct packet_state {
92197679Sdes	u_int32_t seqnr;
93197679Sdes	u_int32_t packets;
94197679Sdes	u_int64_t blocks;
95197679Sdes	u_int64_t bytes;
96197679Sdes};
9757429Smarkm
98197679Sdesstruct packet {
99197679Sdes	TAILQ_ENTRY(packet) next;
100197679Sdes	u_char type;
101197679Sdes	Buffer payload;
102197679Sdes};
10357429Smarkm
104197679Sdesstruct session_state {
105197679Sdes	/*
106197679Sdes	 * This variable contains the file descriptors used for
107197679Sdes	 * communicating with the other side.  connection_in is used for
108197679Sdes	 * reading; connection_out for writing.  These can be the same
109197679Sdes	 * descriptor, in which case it is assumed to be a socket.
110197679Sdes	 */
111197679Sdes	int connection_in;
112197679Sdes	int connection_out;
11357429Smarkm
114197679Sdes	/* Protocol flags for the remote side. */
115197679Sdes	u_int remote_protocol_flags;
11657429Smarkm
117197679Sdes	/* Encryption context for receiving data.  Only used for decryption. */
118197679Sdes	CipherContext receive_context;
11957429Smarkm
120197679Sdes	/* Encryption context for sending data.  Only used for encryption. */
121197679Sdes	CipherContext send_context;
12257429Smarkm
123197679Sdes	/* Buffer for raw input data from the socket. */
124197679Sdes	Buffer input;
12557429Smarkm
126197679Sdes	/* Buffer for raw output data going to the socket. */
127197679Sdes	Buffer output;
12857429Smarkm
129197679Sdes	/* Buffer for the partial outgoing packet being constructed. */
130197679Sdes	Buffer outgoing_packet;
13157429Smarkm
132197679Sdes	/* Buffer for the incoming packet currently being processed. */
133197679Sdes	Buffer incoming_packet;
13457429Smarkm
135197679Sdes	/* Scratch buffer for packet compression/decompression. */
136197679Sdes	Buffer compression_buffer;
137197679Sdes	int compression_buffer_ready;
13857429Smarkm
139197679Sdes	/*
140197679Sdes	 * Flag indicating whether packet compression/decompression is
141197679Sdes	 * enabled.
142197679Sdes	 */
143197679Sdes	int packet_compression;
14457429Smarkm
145197679Sdes	/* default maximum packet size */
146197679Sdes	u_int max_packet_size;
14757429Smarkm
148197679Sdes	/* Flag indicating whether this module has been initialized. */
149197679Sdes	int initialized;
150149749Sdes
151197679Sdes	/* Set to true if the connection is interactive. */
152197679Sdes	int interactive_mode;
153149749Sdes
154197679Sdes	/* Set to true if we are the server side. */
155197679Sdes	int server_side;
156181111Sdes
157197679Sdes	/* Set to true if we are authenticated. */
158197679Sdes	int after_authentication;
159181111Sdes
160197679Sdes	int keep_alive_timeouts;
16160573Skris
162197679Sdes	/* The maximum time that we will wait to send or receive a packet */
163197679Sdes	int packet_timeout_ms;
164124208Sdes
165197679Sdes	/* Session key information for Encryption and MAC */
166197679Sdes	Newkeys *newkeys[MODE_MAX];
167197679Sdes	struct packet_state p_read, p_send;
16898675Sdes
169197679Sdes	u_int64_t max_blocks_in, max_blocks_out;
170197679Sdes	u_int32_t rekey_limit;
17160573Skris
172197679Sdes	/* Session key for protocol v1 */
173197679Sdes	u_char ssh1_key[SSH_SESSION_KEY_LENGTH];
174197679Sdes	u_int ssh1_keylen;
175192595Sdes
176197679Sdes	/* roundup current message to extra_pad bytes */
177197679Sdes	u_char extra_pad;
178197679Sdes
179197679Sdes	/* XXX discard incoming data after MAC error */
180197679Sdes	u_int packet_discard;
181197679Sdes	Mac *packet_discard_mac;
182197679Sdes
183197679Sdes	/* Used in packet_read_poll2() */
184197679Sdes	u_int packlen;
185197679Sdes
186197679Sdes	/* Used in packet_send2 */
187197679Sdes	int rekeying;
188197679Sdes
189197679Sdes	/* Used in packet_set_interactive */
190197679Sdes	int set_interactive_called;
191197679Sdes
192197679Sdes	/* Used in packet_set_maxsize */
193197679Sdes	int set_maxsize_called;
194197679Sdes
195197679Sdes	TAILQ_HEAD(, packet) outgoing;
196124208Sdes};
197124208Sdes
198197679Sdesstatic struct session_state *active_state, *backup_state;
199224638Sbrooks#ifdef	NONE_CIPHER_ENABLED
200224638Sbrooksstatic int rekey_requested = 0;
201224638Sbrooks#endif
202197679Sdes
203197679Sdesstatic struct session_state *
204197679Sdesalloc_session_state(void)
205197679Sdes{
206221420Sdes	struct session_state *s = xcalloc(1, sizeof(*s));
207197679Sdes
208221420Sdes	s->connection_in = -1;
209221420Sdes	s->connection_out = -1;
210221420Sdes	s->max_packet_size = 32768;
211221420Sdes	s->packet_timeout_ms = -1;
212221420Sdes	return s;
213197679Sdes}
214197679Sdes
21557429Smarkm/*
21657429Smarkm * Sets the descriptors used for communication.  Disables encryption until
21757429Smarkm * packet_set_encryption_key is called.
21857429Smarkm */
21957429Smarkmvoid
22057429Smarkmpacket_set_connection(int fd_in, int fd_out)
22157429Smarkm{
22269587Sgreen	Cipher *none = cipher_by_name("none");
223106121Sdes
22469587Sgreen	if (none == NULL)
22569587Sgreen		fatal("packet_set_connection: cannot load cipher 'none'");
226197679Sdes	if (active_state == NULL)
227197679Sdes		active_state = alloc_session_state();
228197679Sdes	active_state->connection_in = fd_in;
229197679Sdes	active_state->connection_out = fd_out;
230197679Sdes	cipher_init(&active_state->send_context, none, (const u_char *)"",
231137015Sdes	    0, NULL, 0, CIPHER_ENCRYPT);
232197679Sdes	cipher_init(&active_state->receive_context, none, (const u_char *)"",
233137015Sdes	    0, NULL, 0, CIPHER_DECRYPT);
234197679Sdes	active_state->newkeys[MODE_IN] = active_state->newkeys[MODE_OUT] = NULL;
235197679Sdes	if (!active_state->initialized) {
236197679Sdes		active_state->initialized = 1;
237197679Sdes		buffer_init(&active_state->input);
238197679Sdes		buffer_init(&active_state->output);
239197679Sdes		buffer_init(&active_state->outgoing_packet);
240197679Sdes		buffer_init(&active_state->incoming_packet);
241197679Sdes		TAILQ_INIT(&active_state->outgoing);
242197679Sdes		active_state->p_send.packets = active_state->p_read.packets = 0;
24357429Smarkm	}
24457429Smarkm}
24557429Smarkm
246181111Sdesvoid
247181111Sdespacket_set_timeout(int timeout, int count)
248181111Sdes{
249181111Sdes	if (timeout == 0 || count == 0) {
250197679Sdes		active_state->packet_timeout_ms = -1;
251181111Sdes		return;
252181111Sdes	}
253181111Sdes	if ((INT_MAX / 1000) / count < timeout)
254197679Sdes		active_state->packet_timeout_ms = INT_MAX;
255181111Sdes	else
256197679Sdes		active_state->packet_timeout_ms = timeout * count * 1000;
257181111Sdes}
258181111Sdes
259192595Sdesstatic void
260192595Sdespacket_stop_discard(void)
261192595Sdes{
262197679Sdes	if (active_state->packet_discard_mac) {
263192595Sdes		char buf[1024];
264192595Sdes
265192595Sdes		memset(buf, 'a', sizeof(buf));
266197679Sdes		while (buffer_len(&active_state->incoming_packet) <
267197679Sdes		    PACKET_MAX_SIZE)
268197679Sdes			buffer_append(&active_state->incoming_packet, buf,
269197679Sdes			    sizeof(buf));
270197679Sdes		(void) mac_compute(active_state->packet_discard_mac,
271197679Sdes		    active_state->p_read.seqnr,
272197679Sdes		    buffer_ptr(&active_state->incoming_packet),
273192595Sdes		    PACKET_MAX_SIZE);
274192595Sdes	}
275192595Sdes	logit("Finished discarding for %.200s", get_remote_ipaddr());
276192595Sdes	cleanup_exit(255);
277192595Sdes}
278192595Sdes
279192595Sdesstatic void
280192595Sdespacket_start_discard(Enc *enc, Mac *mac, u_int packet_length, u_int discard)
281192595Sdes{
282192595Sdes	if (enc == NULL || !cipher_is_cbc(enc->cipher))
283192595Sdes		packet_disconnect("Packet corrupt");
284192595Sdes	if (packet_length != PACKET_MAX_SIZE && mac && mac->enabled)
285197679Sdes		active_state->packet_discard_mac = mac;
286197679Sdes	if (buffer_len(&active_state->input) >= discard)
287192595Sdes		packet_stop_discard();
288197679Sdes	active_state->packet_discard = discard -
289197679Sdes	    buffer_len(&active_state->input);
290192595Sdes}
291192595Sdes
29257429Smarkm/* Returns 1 if remote host is connected via socket, 0 if not. */
29357429Smarkm
29457429Smarkmint
29592555Sdespacket_connection_is_on_socket(void)
29657429Smarkm{
29757429Smarkm	struct sockaddr_storage from, to;
29857429Smarkm	socklen_t fromlen, tolen;
29957429Smarkm
30057429Smarkm	/* filedescriptors in and out are the same, so it's a socket */
301197679Sdes	if (active_state->connection_in == active_state->connection_out)
30257429Smarkm		return 1;
30357429Smarkm	fromlen = sizeof(from);
30457429Smarkm	memset(&from, 0, sizeof(from));
305197679Sdes	if (getpeername(active_state->connection_in, (struct sockaddr *)&from,
306197679Sdes	    &fromlen) < 0)
30757429Smarkm		return 0;
30857429Smarkm	tolen = sizeof(to);
30957429Smarkm	memset(&to, 0, sizeof(to));
310197679Sdes	if (getpeername(active_state->connection_out, (struct sockaddr *)&to,
311197679Sdes	    &tolen) < 0)
31257429Smarkm		return 0;
31357429Smarkm	if (fromlen != tolen || memcmp(&from, &to, fromlen) != 0)
31457429Smarkm		return 0;
31557429Smarkm	if (from.ss_family != AF_INET && from.ss_family != AF_INET6)
31657429Smarkm		return 0;
31757429Smarkm	return 1;
31857429Smarkm}
31957429Smarkm
32098675Sdes/*
32198675Sdes * Exports an IV from the CipherContext required to export the key
32298675Sdes * state back from the unprivileged child to the privileged parent
32398675Sdes * process.
32498675Sdes */
32598675Sdes
32698675Sdesvoid
32798675Sdespacket_get_keyiv(int mode, u_char *iv, u_int len)
32898675Sdes{
32998675Sdes	CipherContext *cc;
33098675Sdes
33198675Sdes	if (mode == MODE_OUT)
332197679Sdes		cc = &active_state->send_context;
33398675Sdes	else
334197679Sdes		cc = &active_state->receive_context;
33598675Sdes
33698675Sdes	cipher_get_keyiv(cc, iv, len);
33798675Sdes}
33898675Sdes
33998675Sdesint
34098675Sdespacket_get_keycontext(int mode, u_char *dat)
34198675Sdes{
34298675Sdes	CipherContext *cc;
34398675Sdes
34498675Sdes	if (mode == MODE_OUT)
345197679Sdes		cc = &active_state->send_context;
34698675Sdes	else
347197679Sdes		cc = &active_state->receive_context;
34898675Sdes
34998675Sdes	return (cipher_get_keycontext(cc, dat));
35098675Sdes}
35198675Sdes
35298675Sdesvoid
35398675Sdespacket_set_keycontext(int mode, u_char *dat)
35498675Sdes{
35598675Sdes	CipherContext *cc;
35698675Sdes
35798675Sdes	if (mode == MODE_OUT)
358197679Sdes		cc = &active_state->send_context;
35998675Sdes	else
360197679Sdes		cc = &active_state->receive_context;
36198675Sdes
36298675Sdes	cipher_set_keycontext(cc, dat);
36398675Sdes}
36498675Sdes
36598675Sdesint
36698675Sdespacket_get_keyiv_len(int mode)
36798675Sdes{
36898675Sdes	CipherContext *cc;
36998675Sdes
37098675Sdes	if (mode == MODE_OUT)
371197679Sdes		cc = &active_state->send_context;
37298675Sdes	else
373197679Sdes		cc = &active_state->receive_context;
37498675Sdes
37598675Sdes	return (cipher_get_keyiv_len(cc));
37698675Sdes}
377162852Sdes
37898675Sdesvoid
37998675Sdespacket_set_iv(int mode, u_char *dat)
38098675Sdes{
38198675Sdes	CipherContext *cc;
38298675Sdes
38398675Sdes	if (mode == MODE_OUT)
384197679Sdes		cc = &active_state->send_context;
38598675Sdes	else
386197679Sdes		cc = &active_state->receive_context;
38798675Sdes
38898675Sdes	cipher_set_keyiv(cc, dat);
38998675Sdes}
390162852Sdes
39198675Sdesint
392124208Sdespacket_get_ssh1_cipher(void)
39398675Sdes{
394197679Sdes	return (cipher_get_number(active_state->receive_context.cipher));
39598675Sdes}
39698675Sdes
397124208Sdesvoid
398221420Sdespacket_get_state(int mode, u_int32_t *seqnr, u_int64_t *blocks,
399221420Sdes    u_int32_t *packets, u_int64_t *bytes)
400124208Sdes{
401124208Sdes	struct packet_state *state;
40298675Sdes
403197679Sdes	state = (mode == MODE_IN) ?
404197679Sdes	    &active_state->p_read : &active_state->p_send;
405181111Sdes	if (seqnr)
406181111Sdes		*seqnr = state->seqnr;
407181111Sdes	if (blocks)
408181111Sdes		*blocks = state->blocks;
409181111Sdes	if (packets)
410181111Sdes		*packets = state->packets;
411181111Sdes	if (bytes)
412181111Sdes		*bytes = state->bytes;
41398675Sdes}
41498675Sdes
41598675Sdesvoid
416181111Sdespacket_set_state(int mode, u_int32_t seqnr, u_int64_t blocks, u_int32_t packets,
417181111Sdes    u_int64_t bytes)
41898675Sdes{
419124208Sdes	struct packet_state *state;
420124208Sdes
421197679Sdes	state = (mode == MODE_IN) ?
422197679Sdes	    &active_state->p_read : &active_state->p_send;
423124208Sdes	state->seqnr = seqnr;
424124208Sdes	state->blocks = blocks;
425124208Sdes	state->packets = packets;
426181111Sdes	state->bytes = bytes;
42798675Sdes}
42898675Sdes
42957429Smarkm/* returns 1 if connection is via ipv4 */
43057429Smarkm
43157429Smarkmint
43292555Sdespacket_connection_is_ipv4(void)
43357429Smarkm{
43457429Smarkm	struct sockaddr_storage to;
43557429Smarkm	socklen_t tolen = sizeof(to);
43657429Smarkm
43757429Smarkm	memset(&to, 0, sizeof(to));
438197679Sdes	if (getsockname(active_state->connection_out, (struct sockaddr *)&to,
439197679Sdes	    &tolen) < 0)
44057429Smarkm		return 0;
44198937Sdes	if (to.ss_family == AF_INET)
44298937Sdes		return 1;
44398937Sdes#ifdef IPV4_IN_IPV6
444126274Sdes	if (to.ss_family == AF_INET6 &&
44598937Sdes	    IN6_IS_ADDR_V4MAPPED(&((struct sockaddr_in6 *)&to)->sin6_addr))
44698937Sdes		return 1;
44798937Sdes#endif
44898937Sdes	return 0;
44957429Smarkm}
45057429Smarkm
45157429Smarkm/* Sets the connection into non-blocking mode. */
45257429Smarkm
45357429Smarkmvoid
45492555Sdespacket_set_nonblocking(void)
45557429Smarkm{
45657429Smarkm	/* Set the socket into non-blocking mode. */
457197679Sdes	set_nonblock(active_state->connection_in);
45857429Smarkm
459197679Sdes	if (active_state->connection_out != active_state->connection_in)
460197679Sdes		set_nonblock(active_state->connection_out);
46157429Smarkm}
46257429Smarkm
46357429Smarkm/* Returns the socket used for reading. */
46457429Smarkm
46557429Smarkmint
46692555Sdespacket_get_connection_in(void)
46757429Smarkm{
468197679Sdes	return active_state->connection_in;
46957429Smarkm}
47057429Smarkm
47157429Smarkm/* Returns the descriptor used for writing. */
47257429Smarkm
47357429Smarkmint
47492555Sdespacket_get_connection_out(void)
47557429Smarkm{
476197679Sdes	return active_state->connection_out;
47757429Smarkm}
47857429Smarkm
47957429Smarkm/* Closes the connection and clears and frees internal data structures. */
48057429Smarkm
48157429Smarkmvoid
48292555Sdespacket_close(void)
48357429Smarkm{
484197679Sdes	if (!active_state->initialized)
48557429Smarkm		return;
486197679Sdes	active_state->initialized = 0;
487197679Sdes	if (active_state->connection_in == active_state->connection_out) {
488197679Sdes		shutdown(active_state->connection_out, SHUT_RDWR);
489197679Sdes		close(active_state->connection_out);
49057429Smarkm	} else {
491197679Sdes		close(active_state->connection_in);
492197679Sdes		close(active_state->connection_out);
49357429Smarkm	}
494197679Sdes	buffer_free(&active_state->input);
495197679Sdes	buffer_free(&active_state->output);
496197679Sdes	buffer_free(&active_state->outgoing_packet);
497197679Sdes	buffer_free(&active_state->incoming_packet);
498197679Sdes	if (active_state->compression_buffer_ready) {
499197679Sdes		buffer_free(&active_state->compression_buffer);
50057429Smarkm		buffer_compress_uninit();
50157429Smarkm	}
502197679Sdes	cipher_cleanup(&active_state->send_context);
503197679Sdes	cipher_cleanup(&active_state->receive_context);
50457429Smarkm}
50557429Smarkm
50657429Smarkm/* Sets remote side protocol flags. */
50757429Smarkm
50857429Smarkmvoid
50976259Sgreenpacket_set_protocol_flags(u_int protocol_flags)
51057429Smarkm{
511197679Sdes	active_state->remote_protocol_flags = protocol_flags;
51257429Smarkm}
51357429Smarkm
51457429Smarkm/* Returns the remote protocol flags set earlier by the above function. */
51557429Smarkm
51676259Sgreenu_int
51792555Sdespacket_get_protocol_flags(void)
51857429Smarkm{
519197679Sdes	return active_state->remote_protocol_flags;
52057429Smarkm}
52157429Smarkm
52257429Smarkm/*
52357429Smarkm * Starts packet compression from the next packet on in both directions.
52457429Smarkm * Level is compression level 1 (fastest) - 9 (slow, best) as in gzip.
52557429Smarkm */
52657429Smarkm
52792555Sdesstatic void
52892555Sdespacket_init_compression(void)
52976259Sgreen{
530197679Sdes	if (active_state->compression_buffer_ready == 1)
53176259Sgreen		return;
532197679Sdes	active_state->compression_buffer_ready = 1;
533197679Sdes	buffer_init(&active_state->compression_buffer);
53476259Sgreen}
53576259Sgreen
53676259Sgreenvoid
53757429Smarkmpacket_start_compression(int level)
53857429Smarkm{
539197679Sdes	if (active_state->packet_compression && !compat20)
54057429Smarkm		fatal("Compression already enabled.");
541197679Sdes	active_state->packet_compression = 1;
54276259Sgreen	packet_init_compression();
54376259Sgreen	buffer_compress_init_send(level);
54476259Sgreen	buffer_compress_init_recv();
54557429Smarkm}
54657429Smarkm
54757429Smarkm/*
54857429Smarkm * Causes any further packets to be encrypted using the given key.  The same
54957429Smarkm * key is used for both sending and reception.  However, both directions are
55057429Smarkm * encrypted independently of each other.
55157429Smarkm */
55298675Sdes
55357429Smarkmvoid
554221420Sdespacket_set_encryption_key(const u_char *key, u_int keylen, int number)
55557429Smarkm{
55669587Sgreen	Cipher *cipher = cipher_by_number(number);
557106121Sdes
55869587Sgreen	if (cipher == NULL)
55969587Sgreen		fatal("packet_set_encryption_key: unknown cipher number %d", number);
56060573Skris	if (keylen < 20)
56169587Sgreen		fatal("packet_set_encryption_key: keylen too small: %d", keylen);
56298675Sdes	if (keylen > SSH_SESSION_KEY_LENGTH)
56398675Sdes		fatal("packet_set_encryption_key: keylen too big: %d", keylen);
564197679Sdes	memcpy(active_state->ssh1_key, key, keylen);
565197679Sdes	active_state->ssh1_keylen = keylen;
566197679Sdes	cipher_init(&active_state->send_context, cipher, key, keylen, NULL,
567197679Sdes	    0, CIPHER_ENCRYPT);
568197679Sdes	cipher_init(&active_state->receive_context, cipher, key, keylen, NULL,
569197679Sdes	    0, CIPHER_DECRYPT);
57057429Smarkm}
57157429Smarkm
57298675Sdesu_int
57398675Sdespacket_get_encryption_key(u_char *key)
57498675Sdes{
57598675Sdes	if (key == NULL)
576197679Sdes		return (active_state->ssh1_keylen);
577197679Sdes	memcpy(key, active_state->ssh1_key, active_state->ssh1_keylen);
578197679Sdes	return (active_state->ssh1_keylen);
57998675Sdes}
58098675Sdes
58192555Sdes/* Start constructing a packet to send. */
58257429Smarkmvoid
58392555Sdespacket_start(u_char type)
58457429Smarkm{
58592555Sdes	u_char buf[9];
58692555Sdes	int len;
58757429Smarkm
58892555Sdes	DBG(debug("packet_start[%d]", type));
58992555Sdes	len = compat20 ? 6 : 9;
59092555Sdes	memset(buf, 0, len - 1);
59192555Sdes	buf[len - 1] = type;
592197679Sdes	buffer_clear(&active_state->outgoing_packet);
593197679Sdes	buffer_append(&active_state->outgoing_packet, buf, len);
59457429Smarkm}
59557429Smarkm
59692555Sdes/* Append payload. */
59760573Skrisvoid
59857429Smarkmpacket_put_char(int value)
59957429Smarkm{
60057429Smarkm	char ch = value;
601106121Sdes
602197679Sdes	buffer_append(&active_state->outgoing_packet, &ch, 1);
60357429Smarkm}
604162852Sdes
60557429Smarkmvoid
60676259Sgreenpacket_put_int(u_int value)
60757429Smarkm{
608197679Sdes	buffer_put_int(&active_state->outgoing_packet, value);
60957429Smarkm}
610162852Sdes
61157429Smarkmvoid
612197679Sdespacket_put_int64(u_int64_t value)
613197679Sdes{
614197679Sdes	buffer_put_int64(&active_state->outgoing_packet, value);
615197679Sdes}
616197679Sdes
617197679Sdesvoid
61892555Sdespacket_put_string(const void *buf, u_int len)
61957429Smarkm{
620197679Sdes	buffer_put_string(&active_state->outgoing_packet, buf, len);
62157429Smarkm}
622162852Sdes
62360573Skrisvoid
62460573Skrispacket_put_cstring(const char *str)
62560573Skris{
626197679Sdes	buffer_put_cstring(&active_state->outgoing_packet, str);
62760573Skris}
628162852Sdes
62960573Skrisvoid
63092555Sdespacket_put_raw(const void *buf, u_int len)
63160573Skris{
632197679Sdes	buffer_append(&active_state->outgoing_packet, buf, len);
63360573Skris}
634162852Sdes
63557429Smarkmvoid
63657429Smarkmpacket_put_bignum(BIGNUM * value)
63757429Smarkm{
638197679Sdes	buffer_put_bignum(&active_state->outgoing_packet, value);
63957429Smarkm}
640162852Sdes
64160573Skrisvoid
64260573Skrispacket_put_bignum2(BIGNUM * value)
64360573Skris{
644197679Sdes	buffer_put_bignum2(&active_state->outgoing_packet, value);
64560573Skris}
64657429Smarkm
647221420Sdes#ifdef OPENSSL_HAS_ECC
648221420Sdesvoid
649221420Sdespacket_put_ecpoint(const EC_GROUP *curve, const EC_POINT *point)
650221420Sdes{
651221420Sdes	buffer_put_ecpoint(&active_state->outgoing_packet, curve, point);
652221420Sdes}
653221420Sdes#endif
654221420Sdes
65557429Smarkm/*
65657429Smarkm * Finalizes and sends the packet.  If the encryption key has been set,
65757429Smarkm * encrypts the packet before sending.
65857429Smarkm */
65957429Smarkm
66092555Sdesstatic void
66176259Sgreenpacket_send1(void)
66257429Smarkm{
66392555Sdes	u_char buf[8], *cp;
66457429Smarkm	int i, padding, len;
66576259Sgreen	u_int checksum;
666137015Sdes	u_int32_t rnd = 0;
66757429Smarkm
66857429Smarkm	/*
66957429Smarkm	 * If using packet compression, compress the payload of the outgoing
67057429Smarkm	 * packet.
67157429Smarkm	 */
672197679Sdes	if (active_state->packet_compression) {
673197679Sdes		buffer_clear(&active_state->compression_buffer);
67457429Smarkm		/* Skip padding. */
675197679Sdes		buffer_consume(&active_state->outgoing_packet, 8);
67657429Smarkm		/* padding */
677197679Sdes		buffer_append(&active_state->compression_buffer,
678197679Sdes		    "\0\0\0\0\0\0\0\0", 8);
679197679Sdes		buffer_compress(&active_state->outgoing_packet,
680197679Sdes		    &active_state->compression_buffer);
681197679Sdes		buffer_clear(&active_state->outgoing_packet);
682197679Sdes		buffer_append(&active_state->outgoing_packet,
683197679Sdes		    buffer_ptr(&active_state->compression_buffer),
684197679Sdes		    buffer_len(&active_state->compression_buffer));
68557429Smarkm	}
68657429Smarkm	/* Compute packet length without padding (add checksum, remove padding). */
687197679Sdes	len = buffer_len(&active_state->outgoing_packet) + 4 - 8;
68857429Smarkm
68960573Skris	/* Insert padding. Initialized to zero in packet_start1() */
69057429Smarkm	padding = 8 - len % 8;
691197679Sdes	if (!active_state->send_context.plaintext) {
692197679Sdes		cp = buffer_ptr(&active_state->outgoing_packet);
69357429Smarkm		for (i = 0; i < padding; i++) {
69457429Smarkm			if (i % 4 == 0)
695137015Sdes				rnd = arc4random();
696137015Sdes			cp[7 - i] = rnd & 0xff;
697137015Sdes			rnd >>= 8;
69857429Smarkm		}
69957429Smarkm	}
700197679Sdes	buffer_consume(&active_state->outgoing_packet, 8 - padding);
70157429Smarkm
70257429Smarkm	/* Add check bytes. */
703197679Sdes	checksum = ssh_crc32(buffer_ptr(&active_state->outgoing_packet),
704197679Sdes	    buffer_len(&active_state->outgoing_packet));
705162852Sdes	put_u32(buf, checksum);
706197679Sdes	buffer_append(&active_state->outgoing_packet, buf, 4);
70757429Smarkm
70857429Smarkm#ifdef PACKET_DEBUG
70957429Smarkm	fprintf(stderr, "packet_send plain: ");
710197679Sdes	buffer_dump(&active_state->outgoing_packet);
71157429Smarkm#endif
71257429Smarkm
71357429Smarkm	/* Append to output. */
714162852Sdes	put_u32(buf, len);
715197679Sdes	buffer_append(&active_state->output, buf, 4);
716197679Sdes	cp = buffer_append_space(&active_state->output,
717197679Sdes	    buffer_len(&active_state->outgoing_packet));
718197679Sdes	cipher_crypt(&active_state->send_context, cp,
719197679Sdes	    buffer_ptr(&active_state->outgoing_packet),
720197679Sdes	    buffer_len(&active_state->outgoing_packet));
72157429Smarkm
72257429Smarkm#ifdef PACKET_DEBUG
72357429Smarkm	fprintf(stderr, "encrypted: ");
724197679Sdes	buffer_dump(&active_state->output);
72557429Smarkm#endif
726197679Sdes	active_state->p_send.packets++;
727197679Sdes	active_state->p_send.bytes += len +
728197679Sdes	    buffer_len(&active_state->outgoing_packet);
729197679Sdes	buffer_clear(&active_state->outgoing_packet);
73057429Smarkm
73157429Smarkm	/*
732157016Sdes	 * Note that the packet is now only buffered in output.  It won't be
73357429Smarkm	 * actually sent until packet_write_wait or packet_write_poll is
73457429Smarkm	 * called.
73557429Smarkm	 */
73657429Smarkm}
73757429Smarkm
73898675Sdesvoid
73976259Sgreenset_newkeys(int mode)
74076259Sgreen{
74176259Sgreen	Enc *enc;
74276259Sgreen	Mac *mac;
74376259Sgreen	Comp *comp;
74476259Sgreen	CipherContext *cc;
745124208Sdes	u_int64_t *max_blocks;
746137015Sdes	int crypt_type;
74776259Sgreen
748113908Sdes	debug2("set_newkeys: mode %d", mode);
74976259Sgreen
75092555Sdes	if (mode == MODE_OUT) {
751197679Sdes		cc = &active_state->send_context;
752137015Sdes		crypt_type = CIPHER_ENCRYPT;
753197679Sdes		active_state->p_send.packets = active_state->p_send.blocks = 0;
754197679Sdes		max_blocks = &active_state->max_blocks_out;
75592555Sdes	} else {
756197679Sdes		cc = &active_state->receive_context;
757137015Sdes		crypt_type = CIPHER_DECRYPT;
758197679Sdes		active_state->p_read.packets = active_state->p_read.blocks = 0;
759197679Sdes		max_blocks = &active_state->max_blocks_in;
76092555Sdes	}
761197679Sdes	if (active_state->newkeys[mode] != NULL) {
762113908Sdes		debug("set_newkeys: rekeying");
76392555Sdes		cipher_cleanup(cc);
764197679Sdes		enc  = &active_state->newkeys[mode]->enc;
765197679Sdes		mac  = &active_state->newkeys[mode]->mac;
766197679Sdes		comp = &active_state->newkeys[mode]->comp;
767181111Sdes		mac_clear(mac);
76876259Sgreen		xfree(enc->name);
76976259Sgreen		xfree(enc->iv);
77076259Sgreen		xfree(enc->key);
77176259Sgreen		xfree(mac->name);
77276259Sgreen		xfree(mac->key);
77376259Sgreen		xfree(comp->name);
774197679Sdes		xfree(active_state->newkeys[mode]);
77576259Sgreen	}
776197679Sdes	active_state->newkeys[mode] = kex_get_newkeys(mode);
777197679Sdes	if (active_state->newkeys[mode] == NULL)
77876259Sgreen		fatal("newkeys: no keys for mode %d", mode);
779197679Sdes	enc  = &active_state->newkeys[mode]->enc;
780197679Sdes	mac  = &active_state->newkeys[mode]->mac;
781197679Sdes	comp = &active_state->newkeys[mode]->comp;
782181111Sdes	if (mac_init(mac) == 0)
78376259Sgreen		mac->enabled = 1;
78476259Sgreen	DBG(debug("cipher_init_context: %d", mode));
78592555Sdes	cipher_init(cc, enc->cipher, enc->key, enc->key_len,
786137015Sdes	    enc->iv, enc->block_size, crypt_type);
78798675Sdes	/* Deleting the keys does not gain extra security */
78898675Sdes	/* memset(enc->iv,  0, enc->block_size);
789181111Sdes	   memset(enc->key, 0, enc->key_len);
790181111Sdes	   memset(mac->key, 0, mac->key_len); */
791149749Sdes	if ((comp->type == COMP_ZLIB ||
792197679Sdes	    (comp->type == COMP_DELAYED &&
793197679Sdes	     active_state->after_authentication)) && comp->enabled == 0) {
79476259Sgreen		packet_init_compression();
79576259Sgreen		if (mode == MODE_OUT)
79676259Sgreen			buffer_compress_init_send(6);
79776259Sgreen		else
79876259Sgreen			buffer_compress_init_recv();
79976259Sgreen		comp->enabled = 1;
80076259Sgreen	}
801124208Sdes	/*
802124208Sdes	 * The 2^(blocksize*2) limit is too expensive for 3DES,
803124208Sdes	 * blowfish, etc, so enforce a 1GB limit for small blocksizes.
804124208Sdes	 */
805124208Sdes	if (enc->block_size >= 16)
806124208Sdes		*max_blocks = (u_int64_t)1 << (enc->block_size*2);
807124208Sdes	else
808124208Sdes		*max_blocks = ((u_int64_t)1 << 30) / enc->block_size;
809197679Sdes	if (active_state->rekey_limit)
810197679Sdes		*max_blocks = MIN(*max_blocks,
811197679Sdes		    active_state->rekey_limit / enc->block_size);
81276259Sgreen}
81376259Sgreen
81457429Smarkm/*
815149749Sdes * Delayed compression for SSH2 is enabled after authentication:
816162852Sdes * This happens on the server side after a SSH2_MSG_USERAUTH_SUCCESS is sent,
817149749Sdes * and on the client side after a SSH2_MSG_USERAUTH_SUCCESS is received.
818149749Sdes */
819149749Sdesstatic void
820149749Sdespacket_enable_delayed_compress(void)
821149749Sdes{
822149749Sdes	Comp *comp = NULL;
823149749Sdes	int mode;
824149749Sdes
825149749Sdes	/*
826149749Sdes	 * Remember that we are past the authentication step, so rekeying
827149749Sdes	 * with COMP_DELAYED will turn on compression immediately.
828149749Sdes	 */
829197679Sdes	active_state->after_authentication = 1;
830149749Sdes	for (mode = 0; mode < MODE_MAX; mode++) {
831162852Sdes		/* protocol error: USERAUTH_SUCCESS received before NEWKEYS */
832197679Sdes		if (active_state->newkeys[mode] == NULL)
833162852Sdes			continue;
834197679Sdes		comp = &active_state->newkeys[mode]->comp;
835149749Sdes		if (comp && !comp->enabled && comp->type == COMP_DELAYED) {
836149749Sdes			packet_init_compression();
837149749Sdes			if (mode == MODE_OUT)
838149749Sdes				buffer_compress_init_send(6);
839149749Sdes			else
840149749Sdes				buffer_compress_init_recv();
841149749Sdes			comp->enabled = 1;
842149749Sdes		}
843149749Sdes	}
844149749Sdes}
845149749Sdes
846149749Sdes/*
84760573Skris * Finalize packet in SSH2 format (compress, mac, encrypt, enqueue)
84860573Skris */
84992555Sdesstatic void
850124208Sdespacket_send2_wrapped(void)
85160573Skris{
85292555Sdes	u_char type, *cp, *macbuf = NULL;
85392555Sdes	u_char padlen, pad;
85476259Sgreen	u_int packet_length = 0;
85592555Sdes	u_int i, len;
856137015Sdes	u_int32_t rnd = 0;
85760573Skris	Enc *enc   = NULL;
85860573Skris	Mac *mac   = NULL;
85960573Skris	Comp *comp = NULL;
86060573Skris	int block_size;
86160573Skris
862197679Sdes	if (active_state->newkeys[MODE_OUT] != NULL) {
863197679Sdes		enc  = &active_state->newkeys[MODE_OUT]->enc;
864197679Sdes		mac  = &active_state->newkeys[MODE_OUT]->mac;
865197679Sdes		comp = &active_state->newkeys[MODE_OUT]->comp;
86660573Skris	}
86792555Sdes	block_size = enc ? enc->block_size : 8;
86860573Skris
869197679Sdes	cp = buffer_ptr(&active_state->outgoing_packet);
87092555Sdes	type = cp[5];
87160573Skris
87260573Skris#ifdef PACKET_DEBUG
87360573Skris	fprintf(stderr, "plain:     ");
874197679Sdes	buffer_dump(&active_state->outgoing_packet);
87560573Skris#endif
87660573Skris
87760573Skris	if (comp && comp->enabled) {
878197679Sdes		len = buffer_len(&active_state->outgoing_packet);
87960573Skris		/* skip header, compress only payload */
880197679Sdes		buffer_consume(&active_state->outgoing_packet, 5);
881197679Sdes		buffer_clear(&active_state->compression_buffer);
882197679Sdes		buffer_compress(&active_state->outgoing_packet,
883197679Sdes		    &active_state->compression_buffer);
884197679Sdes		buffer_clear(&active_state->outgoing_packet);
885197679Sdes		buffer_append(&active_state->outgoing_packet, "\0\0\0\0\0", 5);
886197679Sdes		buffer_append(&active_state->outgoing_packet,
887197679Sdes		    buffer_ptr(&active_state->compression_buffer),
888197679Sdes		    buffer_len(&active_state->compression_buffer));
88960573Skris		DBG(debug("compression: raw %d compressed %d", len,
890197679Sdes		    buffer_len(&active_state->outgoing_packet)));
89160573Skris	}
89260573Skris
89360573Skris	/* sizeof (packet_len + pad_len + payload) */
894197679Sdes	len = buffer_len(&active_state->outgoing_packet);
89560573Skris
89660573Skris	/*
89760573Skris	 * calc size of padding, alloc space, get random data,
89860573Skris	 * minimum padding is 4 bytes
89960573Skris	 */
90060573Skris	padlen = block_size - (len % block_size);
90160573Skris	if (padlen < 4)
90260573Skris		padlen += block_size;
903197679Sdes	if (active_state->extra_pad) {
90492555Sdes		/* will wrap if extra_pad+padlen > 255 */
905197679Sdes		active_state->extra_pad =
906197679Sdes		    roundup(active_state->extra_pad, block_size);
907197679Sdes		pad = active_state->extra_pad -
908197679Sdes		    ((len + padlen) % active_state->extra_pad);
90998675Sdes		debug3("packet_send2: adding %d (len %d padlen %d extra_pad %d)",
910197679Sdes		    pad, len, padlen, active_state->extra_pad);
91192555Sdes		padlen += pad;
912197679Sdes		active_state->extra_pad = 0;
91392555Sdes	}
914197679Sdes	cp = buffer_append_space(&active_state->outgoing_packet, padlen);
915197679Sdes	if (enc && !active_state->send_context.plaintext) {
91660573Skris		/* random padding */
91760573Skris		for (i = 0; i < padlen; i++) {
91860573Skris			if (i % 4 == 0)
919137015Sdes				rnd = arc4random();
920137015Sdes			cp[i] = rnd & 0xff;
921137015Sdes			rnd >>= 8;
92260573Skris		}
92360573Skris	} else {
92460573Skris		/* clear padding */
92560573Skris		memset(cp, 0, padlen);
92660573Skris	}
92760573Skris	/* packet_length includes payload, padding and padding length field */
928197679Sdes	packet_length = buffer_len(&active_state->outgoing_packet) - 4;
929197679Sdes	cp = buffer_ptr(&active_state->outgoing_packet);
930162852Sdes	put_u32(cp, packet_length);
93192555Sdes	cp[4] = padlen;
93260573Skris	DBG(debug("send: len %d (includes padlen %d)", packet_length+4, padlen));
93360573Skris
93460573Skris	/* compute MAC over seqnr and packet(length fields, payload, padding) */
93560573Skris	if (mac && mac->enabled) {
936197679Sdes		macbuf = mac_compute(mac, active_state->p_send.seqnr,
937197679Sdes		    buffer_ptr(&active_state->outgoing_packet),
938197679Sdes		    buffer_len(&active_state->outgoing_packet));
939197679Sdes		DBG(debug("done calc MAC out #%d", active_state->p_send.seqnr));
94060573Skris	}
94160573Skris	/* encrypt packet and append to output buffer. */
942197679Sdes	cp = buffer_append_space(&active_state->output,
943197679Sdes	    buffer_len(&active_state->outgoing_packet));
944197679Sdes	cipher_crypt(&active_state->send_context, cp,
945197679Sdes	    buffer_ptr(&active_state->outgoing_packet),
946197679Sdes	    buffer_len(&active_state->outgoing_packet));
94760573Skris	/* append unencrypted MAC */
94860573Skris	if (mac && mac->enabled)
949197679Sdes		buffer_append(&active_state->output, macbuf, mac->mac_len);
95060573Skris#ifdef PACKET_DEBUG
95160573Skris	fprintf(stderr, "encrypted: ");
952197679Sdes	buffer_dump(&active_state->output);
95360573Skris#endif
95460573Skris	/* increment sequence number for outgoing packets */
955197679Sdes	if (++active_state->p_send.seqnr == 0)
956124208Sdes		logit("outgoing seqnr wraps around");
957197679Sdes	if (++active_state->p_send.packets == 0)
958124208Sdes		if (!(datafellows & SSH_BUG_NOREKEY))
959124208Sdes			fatal("XXX too many packets with same key");
960197679Sdes	active_state->p_send.blocks += (packet_length + 4) / block_size;
961197679Sdes	active_state->p_send.bytes += packet_length + 4;
962197679Sdes	buffer_clear(&active_state->outgoing_packet);
96360573Skris
96476259Sgreen	if (type == SSH2_MSG_NEWKEYS)
96576259Sgreen		set_newkeys(MODE_OUT);
966197679Sdes	else if (type == SSH2_MSG_USERAUTH_SUCCESS && active_state->server_side)
967149749Sdes		packet_enable_delayed_compress();
96860573Skris}
96960573Skris
970124208Sdesstatic void
971124208Sdespacket_send2(void)
972124208Sdes{
973124208Sdes	struct packet *p;
974124208Sdes	u_char type, *cp;
975124208Sdes
976197679Sdes	cp = buffer_ptr(&active_state->outgoing_packet);
977124208Sdes	type = cp[5];
978124208Sdes
979124208Sdes	/* during rekeying we can only send key exchange messages */
980197679Sdes	if (active_state->rekeying) {
981124208Sdes		if (!((type >= SSH2_MSG_TRANSPORT_MIN) &&
982124208Sdes		    (type <= SSH2_MSG_TRANSPORT_MAX))) {
983124208Sdes			debug("enqueue packet: %u", type);
984124208Sdes			p = xmalloc(sizeof(*p));
985124208Sdes			p->type = type;
986197679Sdes			memcpy(&p->payload, &active_state->outgoing_packet,
987197679Sdes			    sizeof(Buffer));
988197679Sdes			buffer_init(&active_state->outgoing_packet);
989197679Sdes			TAILQ_INSERT_TAIL(&active_state->outgoing, p, next);
990124208Sdes			return;
991124208Sdes		}
992124208Sdes	}
993124208Sdes
994124208Sdes	/* rekeying starts with sending KEXINIT */
995124208Sdes	if (type == SSH2_MSG_KEXINIT)
996197679Sdes		active_state->rekeying = 1;
997124208Sdes
998124208Sdes	packet_send2_wrapped();
999124208Sdes
1000124208Sdes	/* after a NEWKEYS message we can send the complete queue */
1001124208Sdes	if (type == SSH2_MSG_NEWKEYS) {
1002197679Sdes		active_state->rekeying = 0;
1003197679Sdes		while ((p = TAILQ_FIRST(&active_state->outgoing))) {
1004124208Sdes			type = p->type;
1005124208Sdes			debug("dequeue packet: %u", type);
1006197679Sdes			buffer_free(&active_state->outgoing_packet);
1007197679Sdes			memcpy(&active_state->outgoing_packet, &p->payload,
1008124208Sdes			    sizeof(Buffer));
1009197679Sdes			TAILQ_REMOVE(&active_state->outgoing, p, next);
1010124208Sdes			xfree(p);
1011124208Sdes			packet_send2_wrapped();
1012124208Sdes		}
1013124208Sdes	}
1014124208Sdes}
1015124208Sdes
101660573Skrisvoid
101792555Sdespacket_send(void)
101860573Skris{
101992555Sdes	if (compat20)
102060573Skris		packet_send2();
102160573Skris	else
102260573Skris		packet_send1();
102360573Skris	DBG(debug("packet_send done"));
102460573Skris}
102560573Skris
102660573Skris/*
102757429Smarkm * Waits until a packet has been received, and returns its type.  Note that
102857429Smarkm * no other data is processed until this returns, so this function should not
102957429Smarkm * be used during the interactive session.
103057429Smarkm */
103157429Smarkm
103257429Smarkmint
103392555Sdespacket_read_seqnr(u_int32_t *seqnr_p)
103457429Smarkm{
1035197679Sdes	int type, len, ret, ms_remain, cont;
103676259Sgreen	fd_set *setp;
103757429Smarkm	char buf[8192];
1038181111Sdes	struct timeval timeout, start, *timeoutp = NULL;
1039181111Sdes
104060573Skris	DBG(debug("packet_read()"));
104157429Smarkm
1042197679Sdes	setp = (fd_set *)xcalloc(howmany(active_state->connection_in + 1,
1043197679Sdes	    NFDBITS), sizeof(fd_mask));
104476259Sgreen
104557429Smarkm	/* Since we are blocking, ensure that all written packets have been sent. */
104657429Smarkm	packet_write_wait();
104757429Smarkm
104857429Smarkm	/* Stay in the loop until we have received a complete packet. */
104957429Smarkm	for (;;) {
105057429Smarkm		/* Try to read a packet from the buffer. */
105192555Sdes		type = packet_read_poll_seqnr(seqnr_p);
105292555Sdes		if (!compat20 && (
105360573Skris		    type == SSH_SMSG_SUCCESS
105457429Smarkm		    || type == SSH_SMSG_FAILURE
105557429Smarkm		    || type == SSH_CMSG_EOF
105660573Skris		    || type == SSH_CMSG_EXIT_CONFIRMATION))
105792555Sdes			packet_check_eom();
105857429Smarkm		/* If we got a packet, return it. */
105976259Sgreen		if (type != SSH_MSG_NONE) {
106076259Sgreen			xfree(setp);
106157429Smarkm			return type;
106276259Sgreen		}
106357429Smarkm		/*
106457429Smarkm		 * Otherwise, wait for some data to arrive, add it to the
106557429Smarkm		 * buffer, and try again.
106657429Smarkm		 */
1067197679Sdes		memset(setp, 0, howmany(active_state->connection_in + 1,
1068197679Sdes		    NFDBITS) * sizeof(fd_mask));
1069197679Sdes		FD_SET(active_state->connection_in, setp);
107057429Smarkm
1071197679Sdes		if (active_state->packet_timeout_ms > 0) {
1072197679Sdes			ms_remain = active_state->packet_timeout_ms;
1073181111Sdes			timeoutp = &timeout;
1074181111Sdes		}
107557429Smarkm		/* Wait for some data to arrive. */
1076181111Sdes		for (;;) {
1077197679Sdes			if (active_state->packet_timeout_ms != -1) {
1078181111Sdes				ms_to_timeval(&timeout, ms_remain);
1079181111Sdes				gettimeofday(&start, NULL);
1080181111Sdes			}
1081197679Sdes			if ((ret = select(active_state->connection_in + 1, setp,
1082197679Sdes			    NULL, NULL, timeoutp)) >= 0)
1083181111Sdes				break;
1084197679Sdes			if (errno != EAGAIN && errno != EINTR &&
1085181111Sdes			    errno != EWOULDBLOCK)
1086181111Sdes				break;
1087197679Sdes			if (active_state->packet_timeout_ms == -1)
1088181111Sdes				continue;
1089181111Sdes			ms_subtract_diff(&start, &ms_remain);
1090181111Sdes			if (ms_remain <= 0) {
1091181111Sdes				ret = 0;
1092181111Sdes				break;
1093181111Sdes			}
1094181111Sdes		}
1095181111Sdes		if (ret == 0) {
1096181111Sdes			logit("Connection to %.200s timed out while "
1097181111Sdes			    "waiting to read", get_remote_ipaddr());
1098181111Sdes			cleanup_exit(255);
1099181111Sdes		}
110057429Smarkm		/* Read data from the socket. */
1101197679Sdes		do {
1102197679Sdes			cont = 0;
1103197679Sdes			len = roaming_read(active_state->connection_in, buf,
1104197679Sdes			    sizeof(buf), &cont);
1105197679Sdes		} while (len == 0 && cont);
110657429Smarkm		if (len == 0) {
1107124208Sdes			logit("Connection closed by %.200s", get_remote_ipaddr());
1108126274Sdes			cleanup_exit(255);
110957429Smarkm		}
111057429Smarkm		if (len < 0)
111157429Smarkm			fatal("Read from socket failed: %.100s", strerror(errno));
111257429Smarkm		/* Append it to the buffer. */
111357429Smarkm		packet_process_incoming(buf, len);
111457429Smarkm	}
111557429Smarkm	/* NOTREACHED */
111657429Smarkm}
111757429Smarkm
111892555Sdesint
111992555Sdespacket_read(void)
112092555Sdes{
112192555Sdes	return packet_read_seqnr(NULL);
112292555Sdes}
112392555Sdes
112457429Smarkm/*
112557429Smarkm * Waits until a packet has been received, verifies that its type matches
112657429Smarkm * that given, and gives a fatal error and exits if there is a mismatch.
112757429Smarkm */
112857429Smarkm
112957429Smarkmvoid
113092555Sdespacket_read_expect(int expected_type)
113157429Smarkm{
113257429Smarkm	int type;
113357429Smarkm
113492555Sdes	type = packet_read();
113557429Smarkm	if (type != expected_type)
113657429Smarkm		packet_disconnect("Protocol error: expected packet type %d, got %d",
113760573Skris		    expected_type, type);
113857429Smarkm}
113957429Smarkm
114057429Smarkm/* Checks if a full packet is available in the data received so far via
114157429Smarkm * packet_process_incoming.  If so, reads the packet; otherwise returns
114257429Smarkm * SSH_MSG_NONE.  This does not wait for data from the connection.
114357429Smarkm *
114457429Smarkm * SSH_MSG_DISCONNECT is handled specially here.  Also,
114557429Smarkm * SSH_MSG_IGNORE messages are skipped by this function and are never returned
114657429Smarkm * to higher levels.
114757429Smarkm */
114857429Smarkm
114992555Sdesstatic int
115092555Sdespacket_read_poll1(void)
115157429Smarkm{
115276259Sgreen	u_int len, padded_len;
115392555Sdes	u_char *cp, type;
115476259Sgreen	u_int checksum, stored_checksum;
115557429Smarkm
115657429Smarkm	/* Check if input size is less than minimum packet size. */
1157197679Sdes	if (buffer_len(&active_state->input) < 4 + 8)
115857429Smarkm		return SSH_MSG_NONE;
115957429Smarkm	/* Get length of incoming packet. */
1160197679Sdes	cp = buffer_ptr(&active_state->input);
1161162852Sdes	len = get_u32(cp);
116257429Smarkm	if (len < 1 + 2 + 2 || len > 256 * 1024)
1163113908Sdes		packet_disconnect("Bad packet length %u.", len);
116457429Smarkm	padded_len = (len + 8) & ~7;
116557429Smarkm
116657429Smarkm	/* Check if the packet has been entirely received. */
1167197679Sdes	if (buffer_len(&active_state->input) < 4 + padded_len)
116857429Smarkm		return SSH_MSG_NONE;
116957429Smarkm
117057429Smarkm	/* The entire packet is in buffer. */
117157429Smarkm
117257429Smarkm	/* Consume packet length. */
1173197679Sdes	buffer_consume(&active_state->input, 4);
117457429Smarkm
117592555Sdes	/*
117692555Sdes	 * Cryptographic attack detector for ssh
117792555Sdes	 * (C)1998 CORE-SDI, Buenos Aires Argentina
117892555Sdes	 * Ariel Futoransky(futo@core-sdi.com)
117992555Sdes	 */
1180197679Sdes	if (!active_state->receive_context.plaintext) {
1181197679Sdes		switch (detect_attack(buffer_ptr(&active_state->input),
1182197679Sdes		    padded_len)) {
1183162852Sdes		case DEATTACK_DETECTED:
1184162852Sdes			packet_disconnect("crc32 compensation attack: "
1185162852Sdes			    "network attack detected");
1186162852Sdes		case DEATTACK_DOS_DETECTED:
1187162852Sdes			packet_disconnect("deattack denial of "
1188162852Sdes			    "service detected");
1189162852Sdes		}
1190162852Sdes	}
119192555Sdes
119292555Sdes	/* Decrypt data to incoming_packet. */
1193197679Sdes	buffer_clear(&active_state->incoming_packet);
1194197679Sdes	cp = buffer_append_space(&active_state->incoming_packet, padded_len);
1195197679Sdes	cipher_crypt(&active_state->receive_context, cp,
1196197679Sdes	    buffer_ptr(&active_state->input), padded_len);
119792555Sdes
1198197679Sdes	buffer_consume(&active_state->input, padded_len);
119957429Smarkm
120057429Smarkm#ifdef PACKET_DEBUG
120157429Smarkm	fprintf(stderr, "read_poll plain: ");
1202197679Sdes	buffer_dump(&active_state->incoming_packet);
120357429Smarkm#endif
120457429Smarkm
120557429Smarkm	/* Compute packet checksum. */
1206197679Sdes	checksum = ssh_crc32(buffer_ptr(&active_state->incoming_packet),
1207197679Sdes	    buffer_len(&active_state->incoming_packet) - 4);
120857429Smarkm
120957429Smarkm	/* Skip padding. */
1210197679Sdes	buffer_consume(&active_state->incoming_packet, 8 - len % 8);
121157429Smarkm
121257429Smarkm	/* Test check bytes. */
1213197679Sdes	if (len != buffer_len(&active_state->incoming_packet))
121492555Sdes		packet_disconnect("packet_read_poll1: len %d != buffer_len %d.",
1215197679Sdes		    len, buffer_len(&active_state->incoming_packet));
121657429Smarkm
1217197679Sdes	cp = (u_char *)buffer_ptr(&active_state->incoming_packet) + len - 4;
1218162852Sdes	stored_checksum = get_u32(cp);
121957429Smarkm	if (checksum != stored_checksum)
122057429Smarkm		packet_disconnect("Corrupted check bytes on input.");
1221197679Sdes	buffer_consume_end(&active_state->incoming_packet, 4);
122257429Smarkm
1223197679Sdes	if (active_state->packet_compression) {
1224197679Sdes		buffer_clear(&active_state->compression_buffer);
1225197679Sdes		buffer_uncompress(&active_state->incoming_packet,
1226197679Sdes		    &active_state->compression_buffer);
1227197679Sdes		buffer_clear(&active_state->incoming_packet);
1228197679Sdes		buffer_append(&active_state->incoming_packet,
1229197679Sdes		    buffer_ptr(&active_state->compression_buffer),
1230197679Sdes		    buffer_len(&active_state->compression_buffer));
123157429Smarkm	}
1232197679Sdes	active_state->p_read.packets++;
1233197679Sdes	active_state->p_read.bytes += padded_len + 4;
1234197679Sdes	type = buffer_get_char(&active_state->incoming_packet);
1235146998Sdes	if (type < SSH_MSG_MIN || type > SSH_MSG_MAX)
1236146998Sdes		packet_disconnect("Invalid ssh1 packet type: %d", type);
123792555Sdes	return type;
123860573Skris}
123957429Smarkm
124092555Sdesstatic int
124192555Sdespacket_read_poll2(u_int32_t *seqnr_p)
124260573Skris{
124376259Sgreen	u_int padlen, need;
124492555Sdes	u_char *macbuf, *cp, type;
1245149749Sdes	u_int maclen, block_size;
124660573Skris	Enc *enc   = NULL;
124760573Skris	Mac *mac   = NULL;
124860573Skris	Comp *comp = NULL;
124957429Smarkm
1250197679Sdes	if (active_state->packet_discard)
1251192595Sdes		return SSH_MSG_NONE;
1252192595Sdes
1253197679Sdes	if (active_state->newkeys[MODE_IN] != NULL) {
1254197679Sdes		enc  = &active_state->newkeys[MODE_IN]->enc;
1255197679Sdes		mac  = &active_state->newkeys[MODE_IN]->mac;
1256197679Sdes		comp = &active_state->newkeys[MODE_IN]->comp;
125757429Smarkm	}
125860573Skris	maclen = mac && mac->enabled ? mac->mac_len : 0;
125992555Sdes	block_size = enc ? enc->block_size : 8;
126060573Skris
1261197679Sdes	if (active_state->packlen == 0) {
126260573Skris		/*
126360573Skris		 * check if input size is less than the cipher block size,
126460573Skris		 * decrypt first block and extract length of incoming packet
126560573Skris		 */
1266197679Sdes		if (buffer_len(&active_state->input) < block_size)
126760573Skris			return SSH_MSG_NONE;
1268197679Sdes		buffer_clear(&active_state->incoming_packet);
1269197679Sdes		cp = buffer_append_space(&active_state->incoming_packet,
127060573Skris		    block_size);
1271197679Sdes		cipher_crypt(&active_state->receive_context, cp,
1272197679Sdes		    buffer_ptr(&active_state->input), block_size);
1273197679Sdes		cp = buffer_ptr(&active_state->incoming_packet);
1274197679Sdes		active_state->packlen = get_u32(cp);
1275197679Sdes		if (active_state->packlen < 1 + 4 ||
1276197679Sdes		    active_state->packlen > PACKET_MAX_SIZE) {
1277124208Sdes#ifdef PACKET_DEBUG
1278197679Sdes			buffer_dump(&active_state->incoming_packet);
1279124208Sdes#endif
1280197679Sdes			logit("Bad packet length %u.", active_state->packlen);
1281197679Sdes			packet_start_discard(enc, mac, active_state->packlen,
1282192595Sdes			    PACKET_MAX_SIZE);
1283192595Sdes			return SSH_MSG_NONE;
128460573Skris		}
1285197679Sdes		DBG(debug("input: packet len %u", active_state->packlen+4));
1286197679Sdes		buffer_consume(&active_state->input, block_size);
128760573Skris	}
128860573Skris	/* we have a partial packet of block_size bytes */
1289197679Sdes	need = 4 + active_state->packlen - block_size;
129060573Skris	DBG(debug("partial packet %d, need %d, maclen %d", block_size,
129160573Skris	    need, maclen));
1292192595Sdes	if (need % block_size != 0) {
1293192595Sdes		logit("padding error: need %d block %d mod %d",
129460573Skris		    need, block_size, need % block_size);
1295197679Sdes		packet_start_discard(enc, mac, active_state->packlen,
1296192595Sdes		    PACKET_MAX_SIZE - block_size);
1297192595Sdes		return SSH_MSG_NONE;
1298192595Sdes	}
129960573Skris	/*
130060573Skris	 * check if the entire packet has been received and
130160573Skris	 * decrypt into incoming_packet
130260573Skris	 */
1303197679Sdes	if (buffer_len(&active_state->input) < need + maclen)
130460573Skris		return SSH_MSG_NONE;
130560573Skris#ifdef PACKET_DEBUG
130660573Skris	fprintf(stderr, "read_poll enc/full: ");
1307197679Sdes	buffer_dump(&active_state->input);
130860573Skris#endif
1309197679Sdes	cp = buffer_append_space(&active_state->incoming_packet, need);
1310197679Sdes	cipher_crypt(&active_state->receive_context, cp,
1311197679Sdes	    buffer_ptr(&active_state->input), need);
1312197679Sdes	buffer_consume(&active_state->input, need);
131360573Skris	/*
131460573Skris	 * compute MAC over seqnr and packet,
131560573Skris	 * increment sequence number for incoming packet
131660573Skris	 */
131760573Skris	if (mac && mac->enabled) {
1318197679Sdes		macbuf = mac_compute(mac, active_state->p_read.seqnr,
1319197679Sdes		    buffer_ptr(&active_state->incoming_packet),
1320197679Sdes		    buffer_len(&active_state->incoming_packet));
1321215116Sdes		if (timingsafe_bcmp(macbuf, buffer_ptr(&active_state->input),
1322197679Sdes		    mac->mac_len) != 0) {
1323192595Sdes			logit("Corrupted MAC on input.");
1324192595Sdes			if (need > PACKET_MAX_SIZE)
1325192595Sdes				fatal("internal error need %d", need);
1326197679Sdes			packet_start_discard(enc, mac, active_state->packlen,
1327192595Sdes			    PACKET_MAX_SIZE - need);
1328192595Sdes			return SSH_MSG_NONE;
1329192595Sdes		}
1330192595Sdes
1331197679Sdes		DBG(debug("MAC #%d ok", active_state->p_read.seqnr));
1332197679Sdes		buffer_consume(&active_state->input, mac->mac_len);
133360573Skris	}
1334192595Sdes	/* XXX now it's safe to use fatal/packet_disconnect */
133592555Sdes	if (seqnr_p != NULL)
1336197679Sdes		*seqnr_p = active_state->p_read.seqnr;
1337197679Sdes	if (++active_state->p_read.seqnr == 0)
1338124208Sdes		logit("incoming seqnr wraps around");
1339197679Sdes	if (++active_state->p_read.packets == 0)
1340124208Sdes		if (!(datafellows & SSH_BUG_NOREKEY))
1341124208Sdes			fatal("XXX too many packets with same key");
1342197679Sdes	active_state->p_read.blocks += (active_state->packlen + 4) / block_size;
1343197679Sdes	active_state->p_read.bytes += active_state->packlen + 4;
134460573Skris
134560573Skris	/* get padlen */
1346197679Sdes	cp = buffer_ptr(&active_state->incoming_packet);
134792555Sdes	padlen = cp[4];
134860573Skris	DBG(debug("input: padlen %d", padlen));
134960573Skris	if (padlen < 4)
135060573Skris		packet_disconnect("Corrupted padlen %d on input.", padlen);
135160573Skris
135260573Skris	/* skip packet size + padlen, discard padding */
1353197679Sdes	buffer_consume(&active_state->incoming_packet, 4 + 1);
1354197679Sdes	buffer_consume_end(&active_state->incoming_packet, padlen);
135560573Skris
1356197679Sdes	DBG(debug("input: len before de-compress %d",
1357197679Sdes	    buffer_len(&active_state->incoming_packet)));
135860573Skris	if (comp && comp->enabled) {
1359197679Sdes		buffer_clear(&active_state->compression_buffer);
1360197679Sdes		buffer_uncompress(&active_state->incoming_packet,
1361197679Sdes		    &active_state->compression_buffer);
1362197679Sdes		buffer_clear(&active_state->incoming_packet);
1363197679Sdes		buffer_append(&active_state->incoming_packet,
1364197679Sdes		    buffer_ptr(&active_state->compression_buffer),
1365197679Sdes		    buffer_len(&active_state->compression_buffer));
1366106121Sdes		DBG(debug("input: len after de-compress %d",
1367197679Sdes		    buffer_len(&active_state->incoming_packet)));
136860573Skris	}
136960573Skris	/*
137060573Skris	 * get packet type, implies consume.
137160573Skris	 * return length of payload (without type field)
137260573Skris	 */
1373197679Sdes	type = buffer_get_char(&active_state->incoming_packet);
1374146998Sdes	if (type < SSH2_MSG_MIN || type >= SSH2_MSG_LOCAL_MIN)
1375146998Sdes		packet_disconnect("Invalid ssh2 packet type: %d", type);
137676259Sgreen	if (type == SSH2_MSG_NEWKEYS)
137776259Sgreen		set_newkeys(MODE_IN);
1378197679Sdes	else if (type == SSH2_MSG_USERAUTH_SUCCESS &&
1379197679Sdes	    !active_state->server_side)
1380149749Sdes		packet_enable_delayed_compress();
138160573Skris#ifdef PACKET_DEBUG
138276259Sgreen	fprintf(stderr, "read/plain[%d]:\r\n", type);
1383197679Sdes	buffer_dump(&active_state->incoming_packet);
138460573Skris#endif
138592555Sdes	/* reset for next packet */
1386197679Sdes	active_state->packlen = 0;
138792555Sdes	return type;
138857429Smarkm}
138957429Smarkm
139060573Skrisint
139192555Sdespacket_read_poll_seqnr(u_int32_t *seqnr_p)
139260573Skris{
139399060Sdes	u_int reason, seqnr;
139492555Sdes	u_char type;
139560573Skris	char *msg;
139692555Sdes
139760573Skris	for (;;) {
139892555Sdes		if (compat20) {
139992555Sdes			type = packet_read_poll2(seqnr_p);
1400181111Sdes			if (type) {
1401197679Sdes				active_state->keep_alive_timeouts = 0;
140260573Skris				DBG(debug("received packet type %d", type));
1403181111Sdes			}
140492555Sdes			switch (type) {
140560573Skris			case SSH2_MSG_IGNORE:
1406181111Sdes				debug3("Received SSH2_MSG_IGNORE");
140760573Skris				break;
140860573Skris			case SSH2_MSG_DEBUG:
140960573Skris				packet_get_char();
141060573Skris				msg = packet_get_string(NULL);
141160573Skris				debug("Remote: %.900s", msg);
141260573Skris				xfree(msg);
141360573Skris				msg = packet_get_string(NULL);
141460573Skris				xfree(msg);
141560573Skris				break;
141660573Skris			case SSH2_MSG_DISCONNECT:
141760573Skris				reason = packet_get_int();
141860573Skris				msg = packet_get_string(NULL);
1419124208Sdes				logit("Received disconnect from %s: %u: %.400s",
142099060Sdes				    get_remote_ipaddr(), reason, msg);
142160573Skris				xfree(msg);
1422126274Sdes				cleanup_exit(255);
142360573Skris				break;
142492555Sdes			case SSH2_MSG_UNIMPLEMENTED:
142592555Sdes				seqnr = packet_get_int();
142699060Sdes				debug("Received SSH2_MSG_UNIMPLEMENTED for %u",
142799060Sdes				    seqnr);
142892555Sdes				break;
142960573Skris			default:
143060573Skris				return type;
143176259Sgreen			}
143260573Skris		} else {
143392555Sdes			type = packet_read_poll1();
143492555Sdes			switch (type) {
143560573Skris			case SSH_MSG_IGNORE:
143660573Skris				break;
143760573Skris			case SSH_MSG_DEBUG:
143860573Skris				msg = packet_get_string(NULL);
143960573Skris				debug("Remote: %.900s", msg);
144060573Skris				xfree(msg);
144160573Skris				break;
144260573Skris			case SSH_MSG_DISCONNECT:
144360573Skris				msg = packet_get_string(NULL);
1444124208Sdes				logit("Received disconnect from %s: %.400s",
144599060Sdes				    get_remote_ipaddr(), msg);
1446126274Sdes				cleanup_exit(255);
144760573Skris				break;
144860573Skris			default:
144992555Sdes				if (type)
145060573Skris					DBG(debug("received packet type %d", type));
145160573Skris				return type;
145276259Sgreen			}
145360573Skris		}
145460573Skris	}
145560573Skris}
145660573Skris
145792555Sdesint
145892555Sdespacket_read_poll(void)
145992555Sdes{
146092555Sdes	return packet_read_poll_seqnr(NULL);
146192555Sdes}
146292555Sdes
146357429Smarkm/*
146457429Smarkm * Buffers the given amount of input characters.  This is intended to be used
146557429Smarkm * together with packet_read_poll.
146657429Smarkm */
146757429Smarkm
146857429Smarkmvoid
146976259Sgreenpacket_process_incoming(const char *buf, u_int len)
147057429Smarkm{
1471197679Sdes	if (active_state->packet_discard) {
1472197679Sdes		active_state->keep_alive_timeouts = 0; /* ?? */
1473197679Sdes		if (len >= active_state->packet_discard)
1474192595Sdes			packet_stop_discard();
1475197679Sdes		active_state->packet_discard -= len;
1476192595Sdes		return;
1477192595Sdes	}
1478197679Sdes	buffer_append(&active_state->input, buf, len);
147957429Smarkm}
148057429Smarkm
148157429Smarkm/* Returns a character from the packet. */
148257429Smarkm
148376259Sgreenu_int
148492555Sdespacket_get_char(void)
148557429Smarkm{
148657429Smarkm	char ch;
1487106121Sdes
1488197679Sdes	buffer_get(&active_state->incoming_packet, &ch, 1);
148976259Sgreen	return (u_char) ch;
149057429Smarkm}
149157429Smarkm
149257429Smarkm/* Returns an integer from the packet data. */
149357429Smarkm
149476259Sgreenu_int
149592555Sdespacket_get_int(void)
149657429Smarkm{
1497197679Sdes	return buffer_get_int(&active_state->incoming_packet);
149857429Smarkm}
149957429Smarkm
1500197679Sdes/* Returns an 64 bit integer from the packet data. */
1501197679Sdes
1502197679Sdesu_int64_t
1503197679Sdespacket_get_int64(void)
1504197679Sdes{
1505197679Sdes	return buffer_get_int64(&active_state->incoming_packet);
1506197679Sdes}
1507197679Sdes
150857429Smarkm/*
150957429Smarkm * Returns an arbitrary precision integer from the packet data.  The integer
151057429Smarkm * must have been initialized before this call.
151157429Smarkm */
151257429Smarkm
151357429Smarkmvoid
151492555Sdespacket_get_bignum(BIGNUM * value)
151557429Smarkm{
1516197679Sdes	buffer_get_bignum(&active_state->incoming_packet, value);
151757429Smarkm}
151857429Smarkm
151960573Skrisvoid
152092555Sdespacket_get_bignum2(BIGNUM * value)
152160573Skris{
1522197679Sdes	buffer_get_bignum2(&active_state->incoming_packet, value);
152360573Skris}
152460573Skris
1525221420Sdes#ifdef OPENSSL_HAS_ECC
1526221420Sdesvoid
1527221420Sdespacket_get_ecpoint(const EC_GROUP *curve, EC_POINT *point)
1528221420Sdes{
1529221420Sdes	buffer_get_ecpoint(&active_state->incoming_packet, curve, point);
1530221420Sdes}
1531221420Sdes#endif
1532221420Sdes
153392555Sdesvoid *
1534149749Sdespacket_get_raw(u_int *length_ptr)
153560573Skris{
1536197679Sdes	u_int bytes = buffer_len(&active_state->incoming_packet);
1537106121Sdes
153860573Skris	if (length_ptr != NULL)
153960573Skris		*length_ptr = bytes;
1540197679Sdes	return buffer_ptr(&active_state->incoming_packet);
154160573Skris}
154260573Skris
154360573Skrisint
154460573Skrispacket_remaining(void)
154560573Skris{
1546197679Sdes	return buffer_len(&active_state->incoming_packet);
154760573Skris}
154860573Skris
154957429Smarkm/*
155057429Smarkm * Returns a string from the packet data.  The string is allocated using
155157429Smarkm * xmalloc; it is the responsibility of the calling program to free it when
155257429Smarkm * no longer needed.  The length_ptr argument may be NULL, or point to an
155357429Smarkm * integer into which the length of the string is stored.
155457429Smarkm */
155557429Smarkm
155692555Sdesvoid *
155776259Sgreenpacket_get_string(u_int *length_ptr)
155857429Smarkm{
1559197679Sdes	return buffer_get_string(&active_state->incoming_packet, length_ptr);
156057429Smarkm}
156157429Smarkm
1562181111Sdesvoid *
1563181111Sdespacket_get_string_ptr(u_int *length_ptr)
1564181111Sdes{
1565197679Sdes	return buffer_get_string_ptr(&active_state->incoming_packet, length_ptr);
1566181111Sdes}
1567181111Sdes
1568221420Sdes/* Ensures the returned string has no embedded \0 characters in it. */
1569221420Sdeschar *
1570221420Sdespacket_get_cstring(u_int *length_ptr)
1571221420Sdes{
1572221420Sdes	return buffer_get_cstring(&active_state->incoming_packet, length_ptr);
1573221420Sdes}
1574221420Sdes
157557429Smarkm/*
157657429Smarkm * Sends a diagnostic message from the server to the client.  This message
157757429Smarkm * can be sent at any time (but not while constructing another message). The
157857429Smarkm * message is printed immediately, but only if the client is being executed
157957429Smarkm * in verbose mode.  These messages are primarily intended to ease debugging
158057429Smarkm * authentication problems.   The length of the formatted message must not
158157429Smarkm * exceed 1024 bytes.  This will automatically call packet_write_wait.
158257429Smarkm */
158357429Smarkm
158457429Smarkmvoid
158557429Smarkmpacket_send_debug(const char *fmt,...)
158657429Smarkm{
158757429Smarkm	char buf[1024];
158857429Smarkm	va_list args;
158957429Smarkm
159076259Sgreen	if (compat20 && (datafellows & SSH_BUG_DEBUG))
159176259Sgreen		return;
159276259Sgreen
159357429Smarkm	va_start(args, fmt);
159457429Smarkm	vsnprintf(buf, sizeof(buf), fmt, args);
159557429Smarkm	va_end(args);
159657429Smarkm
159760573Skris	if (compat20) {
159860573Skris		packet_start(SSH2_MSG_DEBUG);
159960573Skris		packet_put_char(0);	/* bool: always display */
160060573Skris		packet_put_cstring(buf);
160160573Skris		packet_put_cstring("");
160260573Skris	} else {
160360573Skris		packet_start(SSH_MSG_DEBUG);
160460573Skris		packet_put_cstring(buf);
160560573Skris	}
160657429Smarkm	packet_send();
160757429Smarkm	packet_write_wait();
160857429Smarkm}
160957429Smarkm
161057429Smarkm/*
161157429Smarkm * Logs the error plus constructs and sends a disconnect packet, closes the
161257429Smarkm * connection, and exits.  This function never returns. The error message
161357429Smarkm * should not contain a newline.  The length of the formatted message must
161457429Smarkm * not exceed 1024 bytes.
161557429Smarkm */
161657429Smarkm
161757429Smarkmvoid
161857429Smarkmpacket_disconnect(const char *fmt,...)
161957429Smarkm{
162057429Smarkm	char buf[1024];
162157429Smarkm	va_list args;
162257429Smarkm	static int disconnecting = 0;
1623106121Sdes
162457429Smarkm	if (disconnecting)	/* Guard against recursive invocations. */
162557429Smarkm		fatal("packet_disconnect called recursively.");
162657429Smarkm	disconnecting = 1;
162757429Smarkm
162857429Smarkm	/*
162957429Smarkm	 * Format the message.  Note that the caller must make sure the
163057429Smarkm	 * message is of limited size.
163157429Smarkm	 */
163257429Smarkm	va_start(args, fmt);
163357429Smarkm	vsnprintf(buf, sizeof(buf), fmt, args);
163457429Smarkm	va_end(args);
163557429Smarkm
1636113908Sdes	/* Display the error locally */
1637124208Sdes	logit("Disconnecting: %.100s", buf);
1638113908Sdes
163957429Smarkm	/* Send the disconnect message to the other side, and wait for it to get sent. */
164060573Skris	if (compat20) {
164160573Skris		packet_start(SSH2_MSG_DISCONNECT);
164260573Skris		packet_put_int(SSH2_DISCONNECT_PROTOCOL_ERROR);
164360573Skris		packet_put_cstring(buf);
164460573Skris		packet_put_cstring("");
164560573Skris	} else {
164660573Skris		packet_start(SSH_MSG_DISCONNECT);
164792555Sdes		packet_put_cstring(buf);
164860573Skris	}
164957429Smarkm	packet_send();
165057429Smarkm	packet_write_wait();
165157429Smarkm
165257429Smarkm	/* Stop listening for connections. */
165392555Sdes	channel_close_all();
165457429Smarkm
165557429Smarkm	/* Close the connection. */
165657429Smarkm	packet_close();
1657126274Sdes	cleanup_exit(255);
165857429Smarkm}
165957429Smarkm
166057429Smarkm/* Checks if there is any buffered output, and tries to write some of the output. */
166157429Smarkm
166257429Smarkmvoid
166392555Sdespacket_write_poll(void)
166457429Smarkm{
1665197679Sdes	int len = buffer_len(&active_state->output);
1666197679Sdes	int cont;
1667106121Sdes
166857429Smarkm	if (len > 0) {
1669197679Sdes		cont = 0;
1670197679Sdes		len = roaming_write(active_state->connection_out,
1671197679Sdes		    buffer_ptr(&active_state->output), len, &cont);
1672181111Sdes		if (len == -1) {
1673181111Sdes			if (errno == EINTR || errno == EAGAIN ||
1674181111Sdes			    errno == EWOULDBLOCK)
167557429Smarkm				return;
1676181111Sdes			fatal("Write failed: %.100s", strerror(errno));
167757429Smarkm		}
1678197679Sdes		if (len == 0 && !cont)
1679181111Sdes			fatal("Write connection closed");
1680197679Sdes		buffer_consume(&active_state->output, len);
168157429Smarkm	}
168257429Smarkm}
168357429Smarkm
168457429Smarkm/*
168557429Smarkm * Calls packet_write_poll repeatedly until all pending output data has been
168657429Smarkm * written.
168757429Smarkm */
168857429Smarkm
168957429Smarkmvoid
169092555Sdespacket_write_wait(void)
169157429Smarkm{
169276259Sgreen	fd_set *setp;
1693181111Sdes	int ret, ms_remain;
1694181111Sdes	struct timeval start, timeout, *timeoutp = NULL;
169576259Sgreen
1696197679Sdes	setp = (fd_set *)xcalloc(howmany(active_state->connection_out + 1,
1697197679Sdes	    NFDBITS), sizeof(fd_mask));
169857429Smarkm	packet_write_poll();
169957429Smarkm	while (packet_have_data_to_write()) {
1700197679Sdes		memset(setp, 0, howmany(active_state->connection_out + 1,
1701197679Sdes		    NFDBITS) * sizeof(fd_mask));
1702197679Sdes		FD_SET(active_state->connection_out, setp);
1703181111Sdes
1704197679Sdes		if (active_state->packet_timeout_ms > 0) {
1705197679Sdes			ms_remain = active_state->packet_timeout_ms;
1706181111Sdes			timeoutp = &timeout;
1707181111Sdes		}
1708181111Sdes		for (;;) {
1709197679Sdes			if (active_state->packet_timeout_ms != -1) {
1710181111Sdes				ms_to_timeval(&timeout, ms_remain);
1711181111Sdes				gettimeofday(&start, NULL);
1712181111Sdes			}
1713197679Sdes			if ((ret = select(active_state->connection_out + 1,
1714197679Sdes			    NULL, setp, NULL, timeoutp)) >= 0)
1715181111Sdes				break;
1716197679Sdes			if (errno != EAGAIN && errno != EINTR &&
1717181111Sdes			    errno != EWOULDBLOCK)
1718181111Sdes				break;
1719197679Sdes			if (active_state->packet_timeout_ms == -1)
1720181111Sdes				continue;
1721181111Sdes			ms_subtract_diff(&start, &ms_remain);
1722181111Sdes			if (ms_remain <= 0) {
1723181111Sdes				ret = 0;
1724181111Sdes				break;
1725181111Sdes			}
1726181111Sdes		}
1727181111Sdes		if (ret == 0) {
1728181111Sdes			logit("Connection to %.200s timed out while "
1729181111Sdes			    "waiting to write", get_remote_ipaddr());
1730181111Sdes			cleanup_exit(255);
1731181111Sdes		}
173257429Smarkm		packet_write_poll();
173357429Smarkm	}
173476259Sgreen	xfree(setp);
173557429Smarkm}
173657429Smarkm
173757429Smarkm/* Returns true if there is buffered data to write to the connection. */
173857429Smarkm
173957429Smarkmint
174092555Sdespacket_have_data_to_write(void)
174157429Smarkm{
1742197679Sdes	return buffer_len(&active_state->output) != 0;
174357429Smarkm}
174457429Smarkm
174557429Smarkm/* Returns true if there is not too much data to write to the connection. */
174657429Smarkm
174757429Smarkmint
174892555Sdespacket_not_very_much_data_to_write(void)
174957429Smarkm{
1750197679Sdes	if (active_state->interactive_mode)
1751197679Sdes		return buffer_len(&active_state->output) < 16384;
175257429Smarkm	else
1753197679Sdes		return buffer_len(&active_state->output) < 128 * 1024;
175457429Smarkm}
175557429Smarkm
1756113908Sdesstatic void
1757221420Sdespacket_set_tos(int tos)
1758113908Sdes{
1759126274Sdes#if defined(IP_TOS) && !defined(IP_TOS_IS_BROKEN)
1760113908Sdes	if (!packet_connection_is_on_socket() ||
1761113908Sdes	    !packet_connection_is_ipv4())
1762113908Sdes		return;
1763221420Sdes	debug3("%s: set IP_TOS 0x%02x", __func__, tos);
1764197679Sdes	if (setsockopt(active_state->connection_in, IPPROTO_IP, IP_TOS, &tos,
1765113908Sdes	    sizeof(tos)) < 0)
1766113908Sdes		error("setsockopt IP_TOS %d: %.100s:",
1767113908Sdes		    tos, strerror(errno));
1768126274Sdes#endif
1769113908Sdes}
1770113908Sdes
177157429Smarkm/* Informs that the current session is interactive.  Sets IP flags for that. */
177257429Smarkm
177357429Smarkmvoid
1774221420Sdespacket_set_interactive(int interactive, int qos_interactive, int qos_bulk)
177557429Smarkm{
1776197679Sdes	if (active_state->set_interactive_called)
177776259Sgreen		return;
1778197679Sdes	active_state->set_interactive_called = 1;
177976259Sgreen
178057429Smarkm	/* Record that we are in interactive mode. */
1781197679Sdes	active_state->interactive_mode = interactive;
178257429Smarkm
178357429Smarkm	/* Only set socket options if using a socket.  */
178457429Smarkm	if (!packet_connection_is_on_socket())
1785116791Sdes		return;
1786197679Sdes	set_nodelay(active_state->connection_in);
1787221420Sdes	packet_set_tos(interactive ? qos_interactive : qos_bulk);
178857429Smarkm}
178957429Smarkm
179057429Smarkm/* Returns true if the current connection is interactive. */
179157429Smarkm
179257429Smarkmint
179392555Sdespacket_is_interactive(void)
179457429Smarkm{
1795197679Sdes	return active_state->interactive_mode;
179657429Smarkm}
179757429Smarkm
1798137015Sdesint
1799124208Sdespacket_set_maxsize(u_int s)
180057429Smarkm{
1801197679Sdes	if (active_state->set_maxsize_called) {
1802124208Sdes		logit("packet_set_maxsize: called twice: old %d new %d",
1803197679Sdes		    active_state->max_packet_size, s);
180457429Smarkm		return -1;
180557429Smarkm	}
180657429Smarkm	if (s < 4 * 1024 || s > 1024 * 1024) {
1807124208Sdes		logit("packet_set_maxsize: bad size %d", s);
180857429Smarkm		return -1;
180957429Smarkm	}
1810197679Sdes	active_state->set_maxsize_called = 1;
181192555Sdes	debug("packet_set_maxsize: setting to %d", s);
1812197679Sdes	active_state->max_packet_size = s;
181357429Smarkm	return s;
181457429Smarkm}
181576259Sgreen
1816197679Sdesint
1817197679Sdespacket_inc_alive_timeouts(void)
1818197679Sdes{
1819197679Sdes	return ++active_state->keep_alive_timeouts;
1820197679Sdes}
1821197679Sdes
1822197679Sdesvoid
1823197679Sdespacket_set_alive_timeouts(int ka)
1824197679Sdes{
1825197679Sdes	active_state->keep_alive_timeouts = ka;
1826197679Sdes}
1827197679Sdes
1828197679Sdesu_int
1829197679Sdespacket_get_maxsize(void)
1830197679Sdes{
1831197679Sdes	return active_state->max_packet_size;
1832197679Sdes}
1833197679Sdes
183492555Sdes/* roundup current message to pad bytes */
183592555Sdesvoid
183692555Sdespacket_add_padding(u_char pad)
183792555Sdes{
1838197679Sdes	active_state->extra_pad = pad;
183992555Sdes}
184092555Sdes
184176259Sgreen/*
184276259Sgreen * 9.2.  Ignored Data Message
184376259Sgreen *
184476259Sgreen *   byte      SSH_MSG_IGNORE
184576259Sgreen *   string    data
184676259Sgreen *
184776259Sgreen * All implementations MUST understand (and ignore) this message at any
184876259Sgreen * time (after receiving the protocol version). No implementation is
184976259Sgreen * required to send them. This message can be used as an additional
185076259Sgreen * protection measure against advanced traffic analysis techniques.
185176259Sgreen */
185276259Sgreenvoid
185376259Sgreenpacket_send_ignore(int nbytes)
185476259Sgreen{
1855137015Sdes	u_int32_t rnd = 0;
185676259Sgreen	int i;
185776259Sgreen
185876259Sgreen	packet_start(compat20 ? SSH2_MSG_IGNORE : SSH_MSG_IGNORE);
185976259Sgreen	packet_put_int(nbytes);
186092555Sdes	for (i = 0; i < nbytes; i++) {
186176259Sgreen		if (i % 4 == 0)
1862137015Sdes			rnd = arc4random();
1863162852Sdes		packet_put_char((u_char)rnd & 0xff);
1864137015Sdes		rnd >>= 8;
186576259Sgreen	}
186676259Sgreen}
1867124208Sdes
1868224638Sbrooks#ifdef	NONE_CIPHER_ENABLED
1869224638Sbrooksvoid
1870224638Sbrookspacket_request_rekeying(void)
1871224638Sbrooks{
1872224638Sbrooks	rekey_requested = 1;
1873224638Sbrooks}
1874224638Sbrooks#endif
1875224638Sbrooks
1876137015Sdes#define MAX_PACKETS	(1U<<31)
1877124208Sdesint
1878124208Sdespacket_need_rekeying(void)
1879124208Sdes{
1880124208Sdes	if (datafellows & SSH_BUG_NOREKEY)
1881124208Sdes		return 0;
1882224638Sbrooks#ifdef	NONE_CIPHER_ENABLED
1883224638Sbrooks	if (rekey_requested == 1) {
1884224638Sbrooks		rekey_requested = 0;
1885224638Sbrooks		return 1;
1886224638Sbrooks	}
1887224638Sbrooks#endif
1888124208Sdes	return
1889197679Sdes	    (active_state->p_send.packets > MAX_PACKETS) ||
1890197679Sdes	    (active_state->p_read.packets > MAX_PACKETS) ||
1891197679Sdes	    (active_state->max_blocks_out &&
1892197679Sdes	        (active_state->p_send.blocks > active_state->max_blocks_out)) ||
1893197679Sdes	    (active_state->max_blocks_in &&
1894197679Sdes	        (active_state->p_read.blocks > active_state->max_blocks_in));
1895124208Sdes}
1896124208Sdes
1897124208Sdesvoid
1898124208Sdespacket_set_rekey_limit(u_int32_t bytes)
1899124208Sdes{
1900197679Sdes	active_state->rekey_limit = bytes;
1901124208Sdes}
1902149749Sdes
1903149749Sdesvoid
1904149749Sdespacket_set_server(void)
1905149749Sdes{
1906197679Sdes	active_state->server_side = 1;
1907149749Sdes}
1908149749Sdes
1909149749Sdesvoid
1910149749Sdespacket_set_authenticated(void)
1911149749Sdes{
1912197679Sdes	active_state->after_authentication = 1;
1913149749Sdes}
1914197679Sdes
1915197679Sdesvoid *
1916197679Sdespacket_get_input(void)
1917197679Sdes{
1918197679Sdes	return (void *)&active_state->input;
1919197679Sdes}
1920197679Sdes
1921197679Sdesvoid *
1922197679Sdespacket_get_output(void)
1923197679Sdes{
1924197679Sdes	return (void *)&active_state->output;
1925197679Sdes}
1926197679Sdes
1927197679Sdesvoid *
1928197679Sdespacket_get_newkeys(int mode)
1929197679Sdes{
1930197679Sdes	return (void *)active_state->newkeys[mode];
1931197679Sdes}
1932197679Sdes
1933197679Sdes/*
1934197679Sdes * Save the state for the real connection, and use a separate state when
1935197679Sdes * resuming a suspended connection.
1936197679Sdes */
1937197679Sdesvoid
1938197679Sdespacket_backup_state(void)
1939197679Sdes{
1940197679Sdes	struct session_state *tmp;
1941197679Sdes
1942197679Sdes	close(active_state->connection_in);
1943197679Sdes	active_state->connection_in = -1;
1944197679Sdes	close(active_state->connection_out);
1945197679Sdes	active_state->connection_out = -1;
1946197679Sdes	if (backup_state)
1947197679Sdes		tmp = backup_state;
1948197679Sdes	else
1949197679Sdes		tmp = alloc_session_state();
1950197679Sdes	backup_state = active_state;
1951197679Sdes	active_state = tmp;
1952197679Sdes}
1953197679Sdes
1954197679Sdes/*
1955197679Sdes * Swap in the old state when resuming a connecion.
1956197679Sdes */
1957197679Sdesvoid
1958197679Sdespacket_restore_state(void)
1959197679Sdes{
1960197679Sdes	struct session_state *tmp;
1961197679Sdes	void *buf;
1962197679Sdes	u_int len;
1963197679Sdes
1964197679Sdes	tmp = backup_state;
1965197679Sdes	backup_state = active_state;
1966197679Sdes	active_state = tmp;
1967197679Sdes	active_state->connection_in = backup_state->connection_in;
1968197679Sdes	backup_state->connection_in = -1;
1969197679Sdes	active_state->connection_out = backup_state->connection_out;
1970197679Sdes	backup_state->connection_out = -1;
1971197679Sdes	len = buffer_len(&backup_state->input);
1972197679Sdes	if (len > 0) {
1973197679Sdes		buf = buffer_ptr(&backup_state->input);
1974197679Sdes		buffer_append(&active_state->input, buf, len);
1975197679Sdes		buffer_clear(&backup_state->input);
1976197679Sdes		add_recv_bytes(len);
1977197679Sdes	}
1978197679Sdes}
1979224638Sbrooks
1980224638Sbrooks#ifdef	NONE_CIPHER_ENABLED
1981224638Sbrooksint
1982224638Sbrookspacket_get_authentication_state(void)
1983224638Sbrooks{
1984224638Sbrooks	return (active_state->after_authentication);
1985224638Sbrooks}
1986224638Sbrooks#endif
1987