1323124Sdes/* $OpenBSD: packet.c,v 1.234 2016/07/18 11:35:33 markus Exp $ */
257429Smarkm/*
357429Smarkm * Author: Tatu Ylonen <ylo@cs.hut.fi>
457429Smarkm * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
557429Smarkm *                    All rights reserved
657429Smarkm * This file contains code implementing the packet protocol and communication
757429Smarkm * with the other side.  This same code is used both on client and server side.
860573Skris *
965668Skris * As far as I am concerned, the code I have written for this software
1065668Skris * can be used freely for any purpose.  Any derived versions of this
1165668Skris * software must be clearly marked as such, and if the derived work is
1265668Skris * incompatible with the protocol description in the RFC file, it must be
1365668Skris * called by a name other than "ssh" or "Secure Shell".
1465668Skris *
1565668Skris *
1660573Skris * SSH2 packet format added by Markus Friedl.
1792555Sdes * Copyright (c) 2000, 2001 Markus Friedl.  All rights reserved.
1860573Skris *
1965668Skris * Redistribution and use in source and binary forms, with or without
2065668Skris * modification, are permitted provided that the following conditions
2165668Skris * are met:
2265668Skris * 1. Redistributions of source code must retain the above copyright
2365668Skris *    notice, this list of conditions and the following disclaimer.
2465668Skris * 2. Redistributions in binary form must reproduce the above copyright
2565668Skris *    notice, this list of conditions and the following disclaimer in the
2665668Skris *    documentation and/or other materials provided with the distribution.
2765668Skris *
2865668Skris * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
2965668Skris * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
3065668Skris * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
3165668Skris * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
3265668Skris * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
3365668Skris * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
3465668Skris * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
3565668Skris * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
3665668Skris * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
3765668Skris * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3857429Smarkm */
3957429Smarkm
4057429Smarkm#include "includes.h"
41294666Sdes__RCSID("$FreeBSD: stable/10/crypto/openssh/packet.c 323124 2017-09-01 22:52:18Z des $");
42162852Sdes
43295367Sdes#include <sys/param.h>	/* MIN roundup */
44162852Sdes#include <sys/types.h>
45124208Sdes#include "openbsd-compat/sys-queue.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>
56323124Sdes#include <netdb.h>
57162852Sdes#include <stdarg.h>
58162852Sdes#include <stdio.h>
59162852Sdes#include <stdlib.h>
60162852Sdes#include <string.h>
61162852Sdes#include <unistd.h>
62295367Sdes#include <limits.h>
63162852Sdes#include <signal.h>
64255767Sdes#include <time.h>
65162852Sdes
66295367Sdes#include <zlib.h>
67295367Sdes
68295367Sdes#include "buffer.h"	/* typedefs XXX */
69295367Sdes#include "key.h"	/* typedefs XXX */
70295367Sdes
7157429Smarkm#include "xmalloc.h"
7257429Smarkm#include "crc32.h"
7357429Smarkm#include "deattack.h"
7460573Skris#include "compat.h"
7576259Sgreen#include "ssh1.h"
7660573Skris#include "ssh2.h"
7769587Sgreen#include "cipher.h"
78295367Sdes#include "sshkey.h"
7960573Skris#include "kex.h"
80295367Sdes#include "digest.h"
8176259Sgreen#include "mac.h"
8276259Sgreen#include "log.h"
8376259Sgreen#include "canohost.h"
8492555Sdes#include "misc.h"
85295367Sdes#include "channels.h"
8698675Sdes#include "ssh.h"
87295367Sdes#include "packet.h"
88295367Sdes#include "ssherr.h"
89295367Sdes#include "sshbuf.h"
9060573Skris
9160573Skris#ifdef PACKET_DEBUG
9260573Skris#define DBG(x) x
9360573Skris#else
9460573Skris#define DBG(x)
9560573Skris#endif
9660573Skris
97192595Sdes#define PACKET_MAX_SIZE (256 * 1024)
98192595Sdes
99197679Sdesstruct packet_state {
100197679Sdes	u_int32_t seqnr;
101197679Sdes	u_int32_t packets;
102197679Sdes	u_int64_t blocks;
103197679Sdes	u_int64_t bytes;
104197679Sdes};
10557429Smarkm
106197679Sdesstruct packet {
107197679Sdes	TAILQ_ENTRY(packet) next;
108197679Sdes	u_char type;
109295367Sdes	struct sshbuf *payload;
110197679Sdes};
11157429Smarkm
112197679Sdesstruct session_state {
113197679Sdes	/*
114197679Sdes	 * This variable contains the file descriptors used for
115197679Sdes	 * communicating with the other side.  connection_in is used for
116197679Sdes	 * reading; connection_out for writing.  These can be the same
117197679Sdes	 * descriptor, in which case it is assumed to be a socket.
118197679Sdes	 */
119197679Sdes	int connection_in;
120197679Sdes	int connection_out;
12157429Smarkm
122197679Sdes	/* Protocol flags for the remote side. */
123197679Sdes	u_int remote_protocol_flags;
12457429Smarkm
125197679Sdes	/* Encryption context for receiving data.  Only used for decryption. */
126295367Sdes	struct sshcipher_ctx receive_context;
12757429Smarkm
128197679Sdes	/* Encryption context for sending data.  Only used for encryption. */
129295367Sdes	struct sshcipher_ctx send_context;
13057429Smarkm
131197679Sdes	/* Buffer for raw input data from the socket. */
132295367Sdes	struct sshbuf *input;
13357429Smarkm
134197679Sdes	/* Buffer for raw output data going to the socket. */
135295367Sdes	struct sshbuf *output;
13657429Smarkm
137197679Sdes	/* Buffer for the partial outgoing packet being constructed. */
138295367Sdes	struct sshbuf *outgoing_packet;
13957429Smarkm
140197679Sdes	/* Buffer for the incoming packet currently being processed. */
141295367Sdes	struct sshbuf *incoming_packet;
14257429Smarkm
143197679Sdes	/* Scratch buffer for packet compression/decompression. */
144295367Sdes	struct sshbuf *compression_buffer;
14557429Smarkm
146295367Sdes	/* Incoming/outgoing compression dictionaries */
147295367Sdes	z_stream compression_in_stream;
148295367Sdes	z_stream compression_out_stream;
149295367Sdes	int compression_in_started;
150295367Sdes	int compression_out_started;
151295367Sdes	int compression_in_failures;
152295367Sdes	int compression_out_failures;
153295367Sdes
154197679Sdes	/*
155197679Sdes	 * Flag indicating whether packet compression/decompression is
156197679Sdes	 * enabled.
157197679Sdes	 */
158197679Sdes	int packet_compression;
15957429Smarkm
160197679Sdes	/* default maximum packet size */
161197679Sdes	u_int max_packet_size;
16257429Smarkm
163197679Sdes	/* Flag indicating whether this module has been initialized. */
164197679Sdes	int initialized;
165149749Sdes
166197679Sdes	/* Set to true if the connection is interactive. */
167197679Sdes	int interactive_mode;
168149749Sdes
169197679Sdes	/* Set to true if we are the server side. */
170197679Sdes	int server_side;
171181111Sdes
172197679Sdes	/* Set to true if we are authenticated. */
173197679Sdes	int after_authentication;
174181111Sdes
175197679Sdes	int keep_alive_timeouts;
17660573Skris
177197679Sdes	/* The maximum time that we will wait to send or receive a packet */
178197679Sdes	int packet_timeout_ms;
179124208Sdes
180197679Sdes	/* Session key information for Encryption and MAC */
181295367Sdes	struct newkeys *newkeys[MODE_MAX];
182197679Sdes	struct packet_state p_read, p_send;
18398675Sdes
184255767Sdes	/* Volume-based rekeying */
185296781Sdes	u_int64_t max_blocks_in, max_blocks_out, rekey_limit;
18660573Skris
187255767Sdes	/* Time-based rekeying */
188295367Sdes	u_int32_t rekey_interval;	/* how often in seconds */
189255767Sdes	time_t rekey_time;	/* time of last rekeying */
190255767Sdes
191197679Sdes	/* Session key for protocol v1 */
192197679Sdes	u_char ssh1_key[SSH_SESSION_KEY_LENGTH];
193197679Sdes	u_int ssh1_keylen;
194192595Sdes
195197679Sdes	/* roundup current message to extra_pad bytes */
196197679Sdes	u_char extra_pad;
197197679Sdes
198197679Sdes	/* XXX discard incoming data after MAC error */
199197679Sdes	u_int packet_discard;
200323124Sdes	size_t packet_discard_mac_already;
201295367Sdes	struct sshmac *packet_discard_mac;
202197679Sdes
203197679Sdes	/* Used in packet_read_poll2() */
204197679Sdes	u_int packlen;
205197679Sdes
206197679Sdes	/* Used in packet_send2 */
207197679Sdes	int rekeying;
208197679Sdes
209197679Sdes	/* Used in packet_set_interactive */
210197679Sdes	int set_interactive_called;
211197679Sdes
212197679Sdes	/* Used in packet_set_maxsize */
213197679Sdes	int set_maxsize_called;
214197679Sdes
215295367Sdes	/* One-off warning about weak ciphers */
216295367Sdes	int cipher_warning_done;
217295367Sdes
218295367Sdes	/* SSH1 CRC compensation attack detector */
219295367Sdes	struct deattack_ctx deattack;
220295367Sdes
221197679Sdes	TAILQ_HEAD(, packet) outgoing;
222124208Sdes};
223124208Sdes
224295367Sdesstruct ssh *
225295367Sdesssh_alloc_session_state(void)
226197679Sdes{
227295367Sdes	struct ssh *ssh = NULL;
228295367Sdes	struct session_state *state = NULL;
229197679Sdes
230295367Sdes	if ((ssh = calloc(1, sizeof(*ssh))) == NULL ||
231295367Sdes	    (state = calloc(1, sizeof(*state))) == NULL ||
232295367Sdes	    (state->input = sshbuf_new()) == NULL ||
233295367Sdes	    (state->output = sshbuf_new()) == NULL ||
234295367Sdes	    (state->outgoing_packet = sshbuf_new()) == NULL ||
235295367Sdes	    (state->incoming_packet = sshbuf_new()) == NULL)
236295367Sdes		goto fail;
237295367Sdes	TAILQ_INIT(&state->outgoing);
238295367Sdes	TAILQ_INIT(&ssh->private_keys);
239295367Sdes	TAILQ_INIT(&ssh->public_keys);
240295367Sdes	state->connection_in = -1;
241295367Sdes	state->connection_out = -1;
242295367Sdes	state->max_packet_size = 32768;
243295367Sdes	state->packet_timeout_ms = -1;
244295367Sdes	state->p_send.packets = state->p_read.packets = 0;
245295367Sdes	state->initialized = 1;
246295367Sdes	/*
247295367Sdes	 * ssh_packet_send2() needs to queue packets until
248295367Sdes	 * we've done the initial key exchange.
249295367Sdes	 */
250295367Sdes	state->rekeying = 1;
251295367Sdes	ssh->state = state;
252295367Sdes	return ssh;
253295367Sdes fail:
254295367Sdes	if (state) {
255295367Sdes		sshbuf_free(state->input);
256295367Sdes		sshbuf_free(state->output);
257295367Sdes		sshbuf_free(state->incoming_packet);
258295367Sdes		sshbuf_free(state->outgoing_packet);
259295367Sdes		free(state);
260295367Sdes	}
261295367Sdes	free(ssh);
262295367Sdes	return NULL;
263197679Sdes}
264197679Sdes
265296781Sdes/* Returns nonzero if rekeying is in progress */
266296781Sdesint
267296781Sdesssh_packet_is_rekeying(struct ssh *ssh)
268296781Sdes{
269296781Sdes	return compat20 &&
270296781Sdes	    (ssh->state->rekeying || (ssh->kex != NULL && ssh->kex->done == 0));
271296781Sdes}
272296781Sdes
27357429Smarkm/*
27457429Smarkm * Sets the descriptors used for communication.  Disables encryption until
27557429Smarkm * packet_set_encryption_key is called.
27657429Smarkm */
277295367Sdesstruct ssh *
278295367Sdesssh_packet_set_connection(struct ssh *ssh, int fd_in, int fd_out)
27957429Smarkm{
280295367Sdes	struct session_state *state;
281295367Sdes	const struct sshcipher *none = cipher_by_name("none");
282295367Sdes	int r;
283106121Sdes
284295367Sdes	if (none == NULL) {
285295367Sdes		error("%s: cannot load cipher 'none'", __func__);
286295367Sdes		return NULL;
28757429Smarkm	}
288295367Sdes	if (ssh == NULL)
289295367Sdes		ssh = ssh_alloc_session_state();
290295367Sdes	if (ssh == NULL) {
291295367Sdes		error("%s: cound not allocate state", __func__);
292295367Sdes		return NULL;
293295367Sdes	}
294295367Sdes	state = ssh->state;
295295367Sdes	state->connection_in = fd_in;
296295367Sdes	state->connection_out = fd_out;
297295367Sdes	if ((r = cipher_init(&state->send_context, none,
298295367Sdes	    (const u_char *)"", 0, NULL, 0, CIPHER_ENCRYPT)) != 0 ||
299295367Sdes	    (r = cipher_init(&state->receive_context, none,
300295367Sdes	    (const u_char *)"", 0, NULL, 0, CIPHER_DECRYPT)) != 0) {
301295367Sdes		error("%s: cipher_init failed: %s", __func__, ssh_err(r));
302323124Sdes		free(ssh); /* XXX need ssh_free_session_state? */
303295367Sdes		return NULL;
304295367Sdes	}
305295367Sdes	state->newkeys[MODE_IN] = state->newkeys[MODE_OUT] = NULL;
306295367Sdes	deattack_init(&state->deattack);
307295367Sdes	/*
308295367Sdes	 * Cache the IP address of the remote connection for use in error
309295367Sdes	 * messages that might be generated after the connection has closed.
310295367Sdes	 */
311295367Sdes	(void)ssh_remote_ipaddr(ssh);
312295367Sdes	return ssh;
31357429Smarkm}
31457429Smarkm
315181111Sdesvoid
316295367Sdesssh_packet_set_timeout(struct ssh *ssh, int timeout, int count)
317181111Sdes{
318295367Sdes	struct session_state *state = ssh->state;
319295367Sdes
320240075Sdes	if (timeout <= 0 || count <= 0) {
321295367Sdes		state->packet_timeout_ms = -1;
322181111Sdes		return;
323181111Sdes	}
324181111Sdes	if ((INT_MAX / 1000) / count < timeout)
325295367Sdes		state->packet_timeout_ms = INT_MAX;
326181111Sdes	else
327295367Sdes		state->packet_timeout_ms = timeout * count * 1000;
328181111Sdes}
329181111Sdes
330295367Sdesint
331295367Sdesssh_packet_stop_discard(struct ssh *ssh)
332192595Sdes{
333295367Sdes	struct session_state *state = ssh->state;
334295367Sdes	int r;
335295367Sdes
336295367Sdes	if (state->packet_discard_mac) {
337192595Sdes		char buf[1024];
338323124Sdes		size_t dlen = PACKET_MAX_SIZE;
339295367Sdes
340323124Sdes		if (dlen > state->packet_discard_mac_already)
341323124Sdes			dlen -= state->packet_discard_mac_already;
342192595Sdes		memset(buf, 'a', sizeof(buf));
343323124Sdes		while (sshbuf_len(state->incoming_packet) < dlen)
344295367Sdes			if ((r = sshbuf_put(state->incoming_packet, buf,
345295367Sdes			    sizeof(buf))) != 0)
346295367Sdes				return r;
347295367Sdes		(void) mac_compute(state->packet_discard_mac,
348295367Sdes		    state->p_read.seqnr,
349323124Sdes		    sshbuf_ptr(state->incoming_packet), dlen,
350295367Sdes		    NULL, 0);
351192595Sdes	}
352296781Sdes	logit("Finished discarding for %.200s port %d",
353296781Sdes	    ssh_remote_ipaddr(ssh), ssh_remote_port(ssh));
354295367Sdes	return SSH_ERR_MAC_INVALID;
355192595Sdes}
356192595Sdes
357295367Sdesstatic int
358295367Sdesssh_packet_start_discard(struct ssh *ssh, struct sshenc *enc,
359323124Sdes    struct sshmac *mac, size_t mac_already, u_int discard)
360192595Sdes{
361295367Sdes	struct session_state *state = ssh->state;
362295367Sdes	int r;
363295367Sdes
364295367Sdes	if (enc == NULL || !cipher_is_cbc(enc->cipher) || (mac && mac->etm)) {
365295367Sdes		if ((r = sshpkt_disconnect(ssh, "Packet corrupt")) != 0)
366295367Sdes			return r;
367295367Sdes		return SSH_ERR_MAC_INVALID;
368295367Sdes	}
369323124Sdes	/*
370323124Sdes	 * Record number of bytes over which the mac has already
371323124Sdes	 * been computed in order to minimize timing attacks.
372323124Sdes	 */
373323124Sdes	if (mac && mac->enabled) {
374295367Sdes		state->packet_discard_mac = mac;
375323124Sdes		state->packet_discard_mac_already = mac_already;
376323124Sdes	}
377323124Sdes	if (sshbuf_len(state->input) >= discard)
378323124Sdes		return ssh_packet_stop_discard(ssh);
379295367Sdes	state->packet_discard = discard - sshbuf_len(state->input);
380295367Sdes	return 0;
381192595Sdes}
382192595Sdes
38357429Smarkm/* Returns 1 if remote host is connected via socket, 0 if not. */
38457429Smarkm
38557429Smarkmint
386295367Sdesssh_packet_connection_is_on_socket(struct ssh *ssh)
38757429Smarkm{
388295367Sdes	struct session_state *state = ssh->state;
38957429Smarkm	struct sockaddr_storage from, to;
39057429Smarkm	socklen_t fromlen, tolen;
39157429Smarkm
392323124Sdes	if (state->connection_in == -1 || state->connection_out == -1)
393323124Sdes		return 0;
394323124Sdes
39557429Smarkm	/* filedescriptors in and out are the same, so it's a socket */
396295367Sdes	if (state->connection_in == state->connection_out)
39757429Smarkm		return 1;
39857429Smarkm	fromlen = sizeof(from);
39957429Smarkm	memset(&from, 0, sizeof(from));
400295367Sdes	if (getpeername(state->connection_in, (struct sockaddr *)&from,
401197679Sdes	    &fromlen) < 0)
40257429Smarkm		return 0;
40357429Smarkm	tolen = sizeof(to);
40457429Smarkm	memset(&to, 0, sizeof(to));
405295367Sdes	if (getpeername(state->connection_out, (struct sockaddr *)&to,
406197679Sdes	    &tolen) < 0)
40757429Smarkm		return 0;
40857429Smarkm	if (fromlen != tolen || memcmp(&from, &to, fromlen) != 0)
40957429Smarkm		return 0;
41057429Smarkm	if (from.ss_family != AF_INET && from.ss_family != AF_INET6)
41157429Smarkm		return 0;
41257429Smarkm	return 1;
41357429Smarkm}
41457429Smarkm
41598675Sdesvoid
416295367Sdesssh_packet_get_bytes(struct ssh *ssh, u_int64_t *ibytes, u_int64_t *obytes)
41798675Sdes{
418295367Sdes	if (ibytes)
419295367Sdes		*ibytes = ssh->state->p_read.bytes;
420295367Sdes	if (obytes)
421295367Sdes		*obytes = ssh->state->p_send.bytes;
42298675Sdes}
42398675Sdes
42498675Sdesint
425295367Sdesssh_packet_connection_af(struct ssh *ssh)
42698675Sdes{
42757429Smarkm	struct sockaddr_storage to;
42857429Smarkm	socklen_t tolen = sizeof(to);
42957429Smarkm
43057429Smarkm	memset(&to, 0, sizeof(to));
431295367Sdes	if (getsockname(ssh->state->connection_out, (struct sockaddr *)&to,
432197679Sdes	    &tolen) < 0)
43357429Smarkm		return 0;
43498937Sdes#ifdef IPV4_IN_IPV6
435126274Sdes	if (to.ss_family == AF_INET6 &&
43698937Sdes	    IN6_IS_ADDR_V4MAPPED(&((struct sockaddr_in6 *)&to)->sin6_addr))
437226046Sdes		return AF_INET;
43898937Sdes#endif
439226046Sdes	return to.ss_family;
44057429Smarkm}
44157429Smarkm
44257429Smarkm/* Sets the connection into non-blocking mode. */
44357429Smarkm
44457429Smarkmvoid
445295367Sdesssh_packet_set_nonblocking(struct ssh *ssh)
44657429Smarkm{
44757429Smarkm	/* Set the socket into non-blocking mode. */
448295367Sdes	set_nonblock(ssh->state->connection_in);
44957429Smarkm
450295367Sdes	if (ssh->state->connection_out != ssh->state->connection_in)
451295367Sdes		set_nonblock(ssh->state->connection_out);
45257429Smarkm}
45357429Smarkm
45457429Smarkm/* Returns the socket used for reading. */
45557429Smarkm
45657429Smarkmint
457295367Sdesssh_packet_get_connection_in(struct ssh *ssh)
45857429Smarkm{
459295367Sdes	return ssh->state->connection_in;
46057429Smarkm}
46157429Smarkm
46257429Smarkm/* Returns the descriptor used for writing. */
46357429Smarkm
46457429Smarkmint
465295367Sdesssh_packet_get_connection_out(struct ssh *ssh)
46657429Smarkm{
467295367Sdes	return ssh->state->connection_out;
46857429Smarkm}
46957429Smarkm
470295367Sdes/*
471295367Sdes * Returns the IP-address of the remote host as a string.  The returned
472295367Sdes * string must not be freed.
473295367Sdes */
474295367Sdes
475295367Sdesconst char *
476295367Sdesssh_remote_ipaddr(struct ssh *ssh)
477295367Sdes{
478296781Sdes	const int sock = ssh->state->connection_in;
479296781Sdes
480295367Sdes	/* Check whether we have cached the ipaddr. */
481296781Sdes	if (ssh->remote_ipaddr == NULL) {
482296781Sdes		if (ssh_packet_connection_is_on_socket(ssh)) {
483296781Sdes			ssh->remote_ipaddr = get_peer_ipaddr(sock);
484323124Sdes			ssh->remote_port = get_peer_port(sock);
485323124Sdes			ssh->local_ipaddr = get_local_ipaddr(sock);
486323124Sdes			ssh->local_port = get_local_port(sock);
487296781Sdes		} else {
488296781Sdes			ssh->remote_ipaddr = strdup("UNKNOWN");
489323124Sdes			ssh->remote_port = 65535;
490323124Sdes			ssh->local_ipaddr = strdup("UNKNOWN");
491323124Sdes			ssh->local_port = 65535;
492296781Sdes		}
493296781Sdes	}
494295367Sdes	return ssh->remote_ipaddr;
495295367Sdes}
496295367Sdes
497296781Sdes/* Returns the port number of the remote host. */
498296781Sdes
499296781Sdesint
500296781Sdesssh_remote_port(struct ssh *ssh)
501296781Sdes{
502296781Sdes	(void)ssh_remote_ipaddr(ssh); /* Will lookup and cache. */
503296781Sdes	return ssh->remote_port;
504296781Sdes}
505296781Sdes
506323124Sdes/*
507323124Sdes * Returns the IP-address of the local host as a string.  The returned
508323124Sdes * string must not be freed.
509323124Sdes */
510323124Sdes
511323124Sdesconst char *
512323124Sdesssh_local_ipaddr(struct ssh *ssh)
513323124Sdes{
514323124Sdes	(void)ssh_remote_ipaddr(ssh); /* Will lookup and cache. */
515323124Sdes	return ssh->local_ipaddr;
516323124Sdes}
517323124Sdes
518323124Sdes/* Returns the port number of the local host. */
519323124Sdes
520323124Sdesint
521323124Sdesssh_local_port(struct ssh *ssh)
522323124Sdes{
523323124Sdes	(void)ssh_remote_ipaddr(ssh); /* Will lookup and cache. */
524323124Sdes	return ssh->local_port;
525323124Sdes}
526323124Sdes
52757429Smarkm/* Closes the connection and clears and frees internal data structures. */
52857429Smarkm
52957429Smarkmvoid
530295367Sdesssh_packet_close(struct ssh *ssh)
53157429Smarkm{
532295367Sdes	struct session_state *state = ssh->state;
533295367Sdes	int r;
534295367Sdes	u_int mode;
535295367Sdes
536295367Sdes	if (!state->initialized)
53757429Smarkm		return;
538295367Sdes	state->initialized = 0;
539295367Sdes	if (state->connection_in == state->connection_out) {
540295367Sdes		shutdown(state->connection_out, SHUT_RDWR);
541295367Sdes		close(state->connection_out);
54257429Smarkm	} else {
543295367Sdes		close(state->connection_in);
544295367Sdes		close(state->connection_out);
54557429Smarkm	}
546295367Sdes	sshbuf_free(state->input);
547295367Sdes	sshbuf_free(state->output);
548295367Sdes	sshbuf_free(state->outgoing_packet);
549295367Sdes	sshbuf_free(state->incoming_packet);
550295367Sdes	for (mode = 0; mode < MODE_MAX; mode++)
551295367Sdes		kex_free_newkeys(state->newkeys[mode]);
552295367Sdes	if (state->compression_buffer) {
553295367Sdes		sshbuf_free(state->compression_buffer);
554295367Sdes		if (state->compression_out_started) {
555295367Sdes			z_streamp stream = &state->compression_out_stream;
556295367Sdes			debug("compress outgoing: "
557295367Sdes			    "raw data %llu, compressed %llu, factor %.2f",
558295367Sdes				(unsigned long long)stream->total_in,
559295367Sdes				(unsigned long long)stream->total_out,
560295367Sdes				stream->total_in == 0 ? 0.0 :
561295367Sdes				(double) stream->total_out / stream->total_in);
562295367Sdes			if (state->compression_out_failures == 0)
563295367Sdes				deflateEnd(stream);
564295367Sdes		}
565295367Sdes		if (state->compression_in_started) {
566295367Sdes			z_streamp stream = &state->compression_out_stream;
567295367Sdes			debug("compress incoming: "
568295367Sdes			    "raw data %llu, compressed %llu, factor %.2f",
569295367Sdes			    (unsigned long long)stream->total_out,
570295367Sdes			    (unsigned long long)stream->total_in,
571295367Sdes			    stream->total_out == 0 ? 0.0 :
572295367Sdes			    (double) stream->total_in / stream->total_out);
573295367Sdes			if (state->compression_in_failures == 0)
574295367Sdes				inflateEnd(stream);
575295367Sdes		}
57657429Smarkm	}
577295367Sdes	if ((r = cipher_cleanup(&state->send_context)) != 0)
578295367Sdes		error("%s: cipher_cleanup failed: %s", __func__, ssh_err(r));
579295367Sdes	if ((r = cipher_cleanup(&state->receive_context)) != 0)
580295367Sdes		error("%s: cipher_cleanup failed: %s", __func__, ssh_err(r));
581296781Sdes	free(ssh->remote_ipaddr);
582296781Sdes	ssh->remote_ipaddr = NULL;
583295367Sdes	free(ssh->state);
584295367Sdes	ssh->state = NULL;
58557429Smarkm}
58657429Smarkm
58757429Smarkm/* Sets remote side protocol flags. */
58857429Smarkm
58957429Smarkmvoid
590295367Sdesssh_packet_set_protocol_flags(struct ssh *ssh, u_int protocol_flags)
59157429Smarkm{
592295367Sdes	ssh->state->remote_protocol_flags = protocol_flags;
59357429Smarkm}
59457429Smarkm
59557429Smarkm/* Returns the remote protocol flags set earlier by the above function. */
59657429Smarkm
59776259Sgreenu_int
598295367Sdesssh_packet_get_protocol_flags(struct ssh *ssh)
59957429Smarkm{
600295367Sdes	return ssh->state->remote_protocol_flags;
60157429Smarkm}
60257429Smarkm
60357429Smarkm/*
60457429Smarkm * Starts packet compression from the next packet on in both directions.
60557429Smarkm * Level is compression level 1 (fastest) - 9 (slow, best) as in gzip.
60657429Smarkm */
60757429Smarkm
608295367Sdesstatic int
609295367Sdesssh_packet_init_compression(struct ssh *ssh)
61076259Sgreen{
611295367Sdes	if (!ssh->state->compression_buffer &&
612295367Sdes	   ((ssh->state->compression_buffer = sshbuf_new()) == NULL))
613295367Sdes		return SSH_ERR_ALLOC_FAIL;
614295367Sdes	return 0;
61576259Sgreen}
61676259Sgreen
617295367Sdesstatic int
618295367Sdesstart_compression_out(struct ssh *ssh, int level)
61957429Smarkm{
620295367Sdes	if (level < 1 || level > 9)
621295367Sdes		return SSH_ERR_INVALID_ARGUMENT;
622295367Sdes	debug("Enabling compression at level %d.", level);
623295367Sdes	if (ssh->state->compression_out_started == 1)
624295367Sdes		deflateEnd(&ssh->state->compression_out_stream);
625295367Sdes	switch (deflateInit(&ssh->state->compression_out_stream, level)) {
626295367Sdes	case Z_OK:
627295367Sdes		ssh->state->compression_out_started = 1;
628295367Sdes		break;
629295367Sdes	case Z_MEM_ERROR:
630295367Sdes		return SSH_ERR_ALLOC_FAIL;
631295367Sdes	default:
632295367Sdes		return SSH_ERR_INTERNAL_ERROR;
633295367Sdes	}
634295367Sdes	return 0;
63557429Smarkm}
63657429Smarkm
637295367Sdesstatic int
638295367Sdesstart_compression_in(struct ssh *ssh)
63957429Smarkm{
640295367Sdes	if (ssh->state->compression_in_started == 1)
641295367Sdes		inflateEnd(&ssh->state->compression_in_stream);
642295367Sdes	switch (inflateInit(&ssh->state->compression_in_stream)) {
643295367Sdes	case Z_OK:
644295367Sdes		ssh->state->compression_in_started = 1;
645295367Sdes		break;
646295367Sdes	case Z_MEM_ERROR:
647295367Sdes		return SSH_ERR_ALLOC_FAIL;
648295367Sdes	default:
649295367Sdes		return SSH_ERR_INTERNAL_ERROR;
650295367Sdes	}
651295367Sdes	return 0;
65257429Smarkm}
65357429Smarkm
654295367Sdesint
655295367Sdesssh_packet_start_compression(struct ssh *ssh, int level)
65698675Sdes{
657295367Sdes	int r;
658295367Sdes
659295367Sdes	if (ssh->state->packet_compression && !compat20)
660295367Sdes		return SSH_ERR_INTERNAL_ERROR;
661295367Sdes	ssh->state->packet_compression = 1;
662295367Sdes	if ((r = ssh_packet_init_compression(ssh)) != 0 ||
663295367Sdes	    (r = start_compression_in(ssh)) != 0 ||
664295367Sdes	    (r = start_compression_out(ssh, level)) != 0)
665295367Sdes		return r;
666295367Sdes	return 0;
66798675Sdes}
66898675Sdes
669295367Sdes/* XXX remove need for separate compression buffer */
670295367Sdesstatic int
671295367Sdescompress_buffer(struct ssh *ssh, struct sshbuf *in, struct sshbuf *out)
67257429Smarkm{
673295367Sdes	u_char buf[4096];
674295367Sdes	int r, status;
67557429Smarkm
676295367Sdes	if (ssh->state->compression_out_started != 1)
677295367Sdes		return SSH_ERR_INTERNAL_ERROR;
678295367Sdes
679295367Sdes	/* This case is not handled below. */
680295367Sdes	if (sshbuf_len(in) == 0)
681295367Sdes		return 0;
682295367Sdes
683295367Sdes	/* Input is the contents of the input buffer. */
684295367Sdes	if ((ssh->state->compression_out_stream.next_in =
685295367Sdes	    sshbuf_mutable_ptr(in)) == NULL)
686295367Sdes		return SSH_ERR_INTERNAL_ERROR;
687295367Sdes	ssh->state->compression_out_stream.avail_in = sshbuf_len(in);
688295367Sdes
689295367Sdes	/* Loop compressing until deflate() returns with avail_out != 0. */
690295367Sdes	do {
691295367Sdes		/* Set up fixed-size output buffer. */
692295367Sdes		ssh->state->compression_out_stream.next_out = buf;
693295367Sdes		ssh->state->compression_out_stream.avail_out = sizeof(buf);
694295367Sdes
695295367Sdes		/* Compress as much data into the buffer as possible. */
696295367Sdes		status = deflate(&ssh->state->compression_out_stream,
697295367Sdes		    Z_PARTIAL_FLUSH);
698295367Sdes		switch (status) {
699295367Sdes		case Z_MEM_ERROR:
700295367Sdes			return SSH_ERR_ALLOC_FAIL;
701295367Sdes		case Z_OK:
702295367Sdes			/* Append compressed data to output_buffer. */
703295367Sdes			if ((r = sshbuf_put(out, buf, sizeof(buf) -
704295367Sdes			    ssh->state->compression_out_stream.avail_out)) != 0)
705295367Sdes				return r;
706295367Sdes			break;
707295367Sdes		case Z_STREAM_ERROR:
708295367Sdes		default:
709295367Sdes			ssh->state->compression_out_failures++;
710295367Sdes			return SSH_ERR_INVALID_FORMAT;
711295367Sdes		}
712295367Sdes	} while (ssh->state->compression_out_stream.avail_out == 0);
713295367Sdes	return 0;
71457429Smarkm}
71557429Smarkm
716295367Sdesstatic int
717295367Sdesuncompress_buffer(struct ssh *ssh, struct sshbuf *in, struct sshbuf *out)
71857429Smarkm{
719295367Sdes	u_char buf[4096];
720295367Sdes	int r, status;
721106121Sdes
722295367Sdes	if (ssh->state->compression_in_started != 1)
723295367Sdes		return SSH_ERR_INTERNAL_ERROR;
724162852Sdes
725295367Sdes	if ((ssh->state->compression_in_stream.next_in =
726295367Sdes	    sshbuf_mutable_ptr(in)) == NULL)
727295367Sdes		return SSH_ERR_INTERNAL_ERROR;
728295367Sdes	ssh->state->compression_in_stream.avail_in = sshbuf_len(in);
729295367Sdes
730295367Sdes	for (;;) {
731295367Sdes		/* Set up fixed-size output buffer. */
732295367Sdes		ssh->state->compression_in_stream.next_out = buf;
733295367Sdes		ssh->state->compression_in_stream.avail_out = sizeof(buf);
734295367Sdes
735295367Sdes		status = inflate(&ssh->state->compression_in_stream,
736295367Sdes		    Z_PARTIAL_FLUSH);
737295367Sdes		switch (status) {
738295367Sdes		case Z_OK:
739295367Sdes			if ((r = sshbuf_put(out, buf, sizeof(buf) -
740295367Sdes			    ssh->state->compression_in_stream.avail_out)) != 0)
741295367Sdes				return r;
742295367Sdes			break;
743295367Sdes		case Z_BUF_ERROR:
744295367Sdes			/*
745295367Sdes			 * Comments in zlib.h say that we should keep calling
746295367Sdes			 * inflate() until we get an error.  This appears to
747295367Sdes			 * be the error that we get.
748295367Sdes			 */
749295367Sdes			return 0;
750295367Sdes		case Z_DATA_ERROR:
751295367Sdes			return SSH_ERR_INVALID_FORMAT;
752295367Sdes		case Z_MEM_ERROR:
753295367Sdes			return SSH_ERR_ALLOC_FAIL;
754295367Sdes		case Z_STREAM_ERROR:
755295367Sdes		default:
756295367Sdes			ssh->state->compression_in_failures++;
757295367Sdes			return SSH_ERR_INTERNAL_ERROR;
758295367Sdes		}
759295367Sdes	}
760295367Sdes	/* NOTREACHED */
76157429Smarkm}
762162852Sdes
763295367Sdes/* Serialise compression state into a blob for privsep */
764295367Sdesstatic int
765295367Sdesssh_packet_get_compress_state(struct sshbuf *m, struct ssh *ssh)
766197679Sdes{
767295367Sdes	struct session_state *state = ssh->state;
768295367Sdes	struct sshbuf *b;
769295367Sdes	int r;
770197679Sdes
771295367Sdes	if ((b = sshbuf_new()) == NULL)
772295367Sdes		return SSH_ERR_ALLOC_FAIL;
773295367Sdes	if (state->compression_in_started) {
774295367Sdes		if ((r = sshbuf_put_string(b, &state->compression_in_stream,
775295367Sdes		    sizeof(state->compression_in_stream))) != 0)
776295367Sdes			goto out;
777295367Sdes	} else if ((r = sshbuf_put_string(b, NULL, 0)) != 0)
778295367Sdes		goto out;
779295367Sdes	if (state->compression_out_started) {
780295367Sdes		if ((r = sshbuf_put_string(b, &state->compression_out_stream,
781295367Sdes		    sizeof(state->compression_out_stream))) != 0)
782295367Sdes			goto out;
783295367Sdes	} else if ((r = sshbuf_put_string(b, NULL, 0)) != 0)
784295367Sdes		goto out;
785295367Sdes	r = sshbuf_put_stringb(m, b);
786295367Sdes out:
787295367Sdes	sshbuf_free(b);
788295367Sdes	return r;
78957429Smarkm}
790162852Sdes
791295367Sdes/* Deserialise compression state from a blob for privsep */
792295367Sdesstatic int
793295367Sdesssh_packet_set_compress_state(struct ssh *ssh, struct sshbuf *m)
79460573Skris{
795295367Sdes	struct session_state *state = ssh->state;
796295367Sdes	struct sshbuf *b = NULL;
797295367Sdes	int r;
798295367Sdes	const u_char *inblob, *outblob;
799295367Sdes	size_t inl, outl;
800162852Sdes
801295367Sdes	if ((r = sshbuf_froms(m, &b)) != 0)
802295367Sdes		goto out;
803295367Sdes	if ((r = sshbuf_get_string_direct(b, &inblob, &inl)) != 0 ||
804295367Sdes	    (r = sshbuf_get_string_direct(b, &outblob, &outl)) != 0)
805295367Sdes		goto out;
806295367Sdes	if (inl == 0)
807295367Sdes		state->compression_in_started = 0;
808295367Sdes	else if (inl != sizeof(state->compression_in_stream)) {
809295367Sdes		r = SSH_ERR_INTERNAL_ERROR;
810295367Sdes		goto out;
811295367Sdes	} else {
812295367Sdes		state->compression_in_started = 1;
813295367Sdes		memcpy(&state->compression_in_stream, inblob, inl);
814295367Sdes	}
815295367Sdes	if (outl == 0)
816295367Sdes		state->compression_out_started = 0;
817295367Sdes	else if (outl != sizeof(state->compression_out_stream)) {
818295367Sdes		r = SSH_ERR_INTERNAL_ERROR;
819295367Sdes		goto out;
820295367Sdes	} else {
821295367Sdes		state->compression_out_started = 1;
822295367Sdes		memcpy(&state->compression_out_stream, outblob, outl);
823295367Sdes	}
824295367Sdes	r = 0;
825295367Sdes out:
826295367Sdes	sshbuf_free(b);
827295367Sdes	return r;
82860573Skris}
829162852Sdes
83057429Smarkmvoid
831295367Sdesssh_packet_set_compress_hooks(struct ssh *ssh, void *ctx,
832295367Sdes    void *(*allocfunc)(void *, u_int, u_int),
833295367Sdes    void (*freefunc)(void *, void *))
83457429Smarkm{
835295367Sdes	ssh->state->compression_out_stream.zalloc = (alloc_func)allocfunc;
836295367Sdes	ssh->state->compression_out_stream.zfree = (free_func)freefunc;
837295367Sdes	ssh->state->compression_out_stream.opaque = ctx;
838295367Sdes	ssh->state->compression_in_stream.zalloc = (alloc_func)allocfunc;
839295367Sdes	ssh->state->compression_in_stream.zfree = (free_func)freefunc;
840295367Sdes	ssh->state->compression_in_stream.opaque = ctx;
84157429Smarkm}
842162852Sdes
843295367Sdes/*
844295367Sdes * Causes any further packets to be encrypted using the given key.  The same
845295367Sdes * key is used for both sending and reception.  However, both directions are
846295367Sdes * encrypted independently of each other.
847295367Sdes */
848295367Sdes
84960573Skrisvoid
850295367Sdesssh_packet_set_encryption_key(struct ssh *ssh, const u_char *key, u_int keylen, int number)
85160573Skris{
852295367Sdes#ifndef WITH_SSH1
853295367Sdes	fatal("no SSH protocol 1 support");
854295367Sdes#else /* WITH_SSH1 */
855295367Sdes	struct session_state *state = ssh->state;
856295367Sdes	const struct sshcipher *cipher = cipher_by_number(number);
857295367Sdes	int r;
858295367Sdes	const char *wmsg;
85957429Smarkm
860295367Sdes	if (cipher == NULL)
861295367Sdes		fatal("%s: unknown cipher number %d", __func__, number);
862295367Sdes	if (keylen < 20)
863295367Sdes		fatal("%s: keylen too small: %d", __func__, keylen);
864295367Sdes	if (keylen > SSH_SESSION_KEY_LENGTH)
865295367Sdes		fatal("%s: keylen too big: %d", __func__, keylen);
866295367Sdes	memcpy(state->ssh1_key, key, keylen);
867295367Sdes	state->ssh1_keylen = keylen;
868295367Sdes	if ((r = cipher_init(&state->send_context, cipher, key, keylen,
869295367Sdes	    NULL, 0, CIPHER_ENCRYPT)) != 0 ||
870295367Sdes	    (r = cipher_init(&state->receive_context, cipher, key, keylen,
871295367Sdes	    NULL, 0, CIPHER_DECRYPT) != 0))
872295367Sdes		fatal("%s: cipher_init failed: %s", __func__, ssh_err(r));
873295367Sdes	if (!state->cipher_warning_done &&
874295367Sdes	    ((wmsg = cipher_warning_message(&state->send_context)) != NULL ||
875295367Sdes	    (wmsg = cipher_warning_message(&state->send_context)) != NULL)) {
876295367Sdes		error("Warning: %s", wmsg);
877295367Sdes		state->cipher_warning_done = 1;
878295367Sdes	}
879295367Sdes#endif /* WITH_SSH1 */
880221420Sdes}
881221420Sdes
88257429Smarkm/*
88357429Smarkm * Finalizes and sends the packet.  If the encryption key has been set,
88457429Smarkm * encrypts the packet before sending.
88557429Smarkm */
88657429Smarkm
887295367Sdesint
888295367Sdesssh_packet_send1(struct ssh *ssh)
88957429Smarkm{
890295367Sdes	struct session_state *state = ssh->state;
89192555Sdes	u_char buf[8], *cp;
892295367Sdes	int r, padding, len;
89376259Sgreen	u_int checksum;
89457429Smarkm
89557429Smarkm	/*
89657429Smarkm	 * If using packet compression, compress the payload of the outgoing
89757429Smarkm	 * packet.
89857429Smarkm	 */
899295367Sdes	if (state->packet_compression) {
900295367Sdes		sshbuf_reset(state->compression_buffer);
90157429Smarkm		/* Skip padding. */
902295367Sdes		if ((r = sshbuf_consume(state->outgoing_packet, 8)) != 0)
903295367Sdes			goto out;
90457429Smarkm		/* padding */
905295367Sdes		if ((r = sshbuf_put(state->compression_buffer,
906295367Sdes		    "\0\0\0\0\0\0\0\0", 8)) != 0)
907295367Sdes			goto out;
908295367Sdes		if ((r = compress_buffer(ssh, state->outgoing_packet,
909295367Sdes		    state->compression_buffer)) != 0)
910295367Sdes			goto out;
911295367Sdes		sshbuf_reset(state->outgoing_packet);
912295367Sdes                if ((r = sshbuf_putb(state->outgoing_packet,
913295367Sdes                    state->compression_buffer)) != 0)
914295367Sdes			goto out;
91557429Smarkm	}
91657429Smarkm	/* Compute packet length without padding (add checksum, remove padding). */
917295367Sdes	len = sshbuf_len(state->outgoing_packet) + 4 - 8;
91857429Smarkm
91960573Skris	/* Insert padding. Initialized to zero in packet_start1() */
92057429Smarkm	padding = 8 - len % 8;
921295367Sdes	if (!state->send_context.plaintext) {
922295367Sdes		cp = sshbuf_mutable_ptr(state->outgoing_packet);
923295367Sdes		if (cp == NULL) {
924295367Sdes			r = SSH_ERR_INTERNAL_ERROR;
925295367Sdes			goto out;
92657429Smarkm		}
927295367Sdes		arc4random_buf(cp + 8 - padding, padding);
92857429Smarkm	}
929295367Sdes	if ((r = sshbuf_consume(state->outgoing_packet, 8 - padding)) != 0)
930295367Sdes		goto out;
93157429Smarkm
93257429Smarkm	/* Add check bytes. */
933295367Sdes	checksum = ssh_crc32(sshbuf_ptr(state->outgoing_packet),
934295367Sdes	    sshbuf_len(state->outgoing_packet));
935295367Sdes	POKE_U32(buf, checksum);
936295367Sdes	if ((r = sshbuf_put(state->outgoing_packet, buf, 4)) != 0)
937295367Sdes		goto out;
93857429Smarkm
93957429Smarkm#ifdef PACKET_DEBUG
94057429Smarkm	fprintf(stderr, "packet_send plain: ");
941295367Sdes	sshbuf_dump(state->outgoing_packet, stderr);
94257429Smarkm#endif
94357429Smarkm
94457429Smarkm	/* Append to output. */
945295367Sdes	POKE_U32(buf, len);
946295367Sdes	if ((r = sshbuf_put(state->output, buf, 4)) != 0)
947295367Sdes		goto out;
948295367Sdes	if ((r = sshbuf_reserve(state->output,
949295367Sdes	    sshbuf_len(state->outgoing_packet), &cp)) != 0)
950295367Sdes		goto out;
951295367Sdes	if ((r = cipher_crypt(&state->send_context, 0, cp,
952295367Sdes	    sshbuf_ptr(state->outgoing_packet),
953295367Sdes	    sshbuf_len(state->outgoing_packet), 0, 0)) != 0)
954295367Sdes		goto out;
95557429Smarkm
95657429Smarkm#ifdef PACKET_DEBUG
95757429Smarkm	fprintf(stderr, "encrypted: ");
958295367Sdes	sshbuf_dump(state->output, stderr);
95957429Smarkm#endif
960295367Sdes	state->p_send.packets++;
961295367Sdes	state->p_send.bytes += len +
962295367Sdes	    sshbuf_len(state->outgoing_packet);
963295367Sdes	sshbuf_reset(state->outgoing_packet);
96457429Smarkm
96557429Smarkm	/*
966157016Sdes	 * Note that the packet is now only buffered in output.  It won't be
967295367Sdes	 * actually sent until ssh_packet_write_wait or ssh_packet_write_poll
968295367Sdes	 * is called.
96957429Smarkm	 */
970295367Sdes	r = 0;
971295367Sdes out:
972295367Sdes	return r;
97357429Smarkm}
97457429Smarkm
975295367Sdesint
976295367Sdesssh_set_newkeys(struct ssh *ssh, int mode)
97776259Sgreen{
978295367Sdes	struct session_state *state = ssh->state;
979295367Sdes	struct sshenc *enc;
980295367Sdes	struct sshmac *mac;
981295367Sdes	struct sshcomp *comp;
982295367Sdes	struct sshcipher_ctx *cc;
983124208Sdes	u_int64_t *max_blocks;
984295367Sdes	const char *wmsg;
985295367Sdes	int r, crypt_type;
98676259Sgreen
987113908Sdes	debug2("set_newkeys: mode %d", mode);
98876259Sgreen
98992555Sdes	if (mode == MODE_OUT) {
990295367Sdes		cc = &state->send_context;
991137015Sdes		crypt_type = CIPHER_ENCRYPT;
992295367Sdes		state->p_send.packets = state->p_send.blocks = 0;
993295367Sdes		max_blocks = &state->max_blocks_out;
99492555Sdes	} else {
995295367Sdes		cc = &state->receive_context;
996137015Sdes		crypt_type = CIPHER_DECRYPT;
997295367Sdes		state->p_read.packets = state->p_read.blocks = 0;
998295367Sdes		max_blocks = &state->max_blocks_in;
99992555Sdes	}
1000295367Sdes	if (state->newkeys[mode] != NULL) {
1001296781Sdes		debug("set_newkeys: rekeying, input %llu bytes %llu blocks, "
1002296781Sdes		   "output %llu bytes %llu blocks",
1003296781Sdes		   (unsigned long long)state->p_read.bytes,
1004296781Sdes		   (unsigned long long)state->p_read.blocks,
1005296781Sdes		   (unsigned long long)state->p_send.bytes,
1006296781Sdes		   (unsigned long long)state->p_send.blocks);
1007295367Sdes		if ((r = cipher_cleanup(cc)) != 0)
1008295367Sdes			return r;
1009295367Sdes		enc  = &state->newkeys[mode]->enc;
1010295367Sdes		mac  = &state->newkeys[mode]->mac;
1011295367Sdes		comp = &state->newkeys[mode]->comp;
1012181111Sdes		mac_clear(mac);
1013264377Sdes		explicit_bzero(enc->iv,  enc->iv_len);
1014264377Sdes		explicit_bzero(enc->key, enc->key_len);
1015264377Sdes		explicit_bzero(mac->key, mac->key_len);
1016255767Sdes		free(enc->name);
1017255767Sdes		free(enc->iv);
1018255767Sdes		free(enc->key);
1019255767Sdes		free(mac->name);
1020255767Sdes		free(mac->key);
1021255767Sdes		free(comp->name);
1022295367Sdes		free(state->newkeys[mode]);
102376259Sgreen	}
1024295367Sdes	/* move newkeys from kex to state */
1025295367Sdes	if ((state->newkeys[mode] = ssh->kex->newkeys[mode]) == NULL)
1026295367Sdes		return SSH_ERR_INTERNAL_ERROR;
1027295367Sdes	ssh->kex->newkeys[mode] = NULL;
1028295367Sdes	enc  = &state->newkeys[mode]->enc;
1029295367Sdes	mac  = &state->newkeys[mode]->mac;
1030295367Sdes	comp = &state->newkeys[mode]->comp;
1031295367Sdes	if (cipher_authlen(enc->cipher) == 0) {
1032295367Sdes		if ((r = mac_init(mac)) != 0)
1033295367Sdes			return r;
1034295367Sdes	}
1035295367Sdes	mac->enabled = 1;
103676259Sgreen	DBG(debug("cipher_init_context: %d", mode));
1037295367Sdes	if ((r = cipher_init(cc, enc->cipher, enc->key, enc->key_len,
1038295367Sdes	    enc->iv, enc->iv_len, crypt_type)) != 0)
1039295367Sdes		return r;
1040295367Sdes	if (!state->cipher_warning_done &&
1041295367Sdes	    (wmsg = cipher_warning_message(cc)) != NULL) {
1042295367Sdes		error("Warning: %s", wmsg);
1043295367Sdes		state->cipher_warning_done = 1;
1044295367Sdes	}
104598675Sdes	/* Deleting the keys does not gain extra security */
1046264377Sdes	/* explicit_bzero(enc->iv,  enc->block_size);
1047264377Sdes	   explicit_bzero(enc->key, enc->key_len);
1048264377Sdes	   explicit_bzero(mac->key, mac->key_len); */
1049149749Sdes	if ((comp->type == COMP_ZLIB ||
1050197679Sdes	    (comp->type == COMP_DELAYED &&
1051295367Sdes	     state->after_authentication)) && comp->enabled == 0) {
1052295367Sdes		if ((r = ssh_packet_init_compression(ssh)) < 0)
1053295367Sdes			return r;
1054295367Sdes		if (mode == MODE_OUT) {
1055295367Sdes			if ((r = start_compression_out(ssh, 6)) != 0)
1056295367Sdes				return r;
1057295367Sdes		} else {
1058295367Sdes			if ((r = start_compression_in(ssh)) != 0)
1059295367Sdes				return r;
1060295367Sdes		}
106176259Sgreen		comp->enabled = 1;
106276259Sgreen	}
1063124208Sdes	/*
1064124208Sdes	 * The 2^(blocksize*2) limit is too expensive for 3DES,
1065124208Sdes	 * blowfish, etc, so enforce a 1GB limit for small blocksizes.
1066124208Sdes	 */
1067124208Sdes	if (enc->block_size >= 16)
1068124208Sdes		*max_blocks = (u_int64_t)1 << (enc->block_size*2);
1069124208Sdes	else
1070124208Sdes		*max_blocks = ((u_int64_t)1 << 30) / enc->block_size;
1071295367Sdes	if (state->rekey_limit)
1072197679Sdes		*max_blocks = MIN(*max_blocks,
1073295367Sdes		    state->rekey_limit / enc->block_size);
1074296781Sdes	debug("rekey after %llu blocks", (unsigned long long)*max_blocks);
1075295367Sdes	return 0;
107676259Sgreen}
107776259Sgreen
1078296781Sdes#define MAX_PACKETS	(1U<<31)
1079296781Sdesstatic int
1080296781Sdesssh_packet_need_rekeying(struct ssh *ssh, u_int outbound_packet_len)
1081296781Sdes{
1082296781Sdes	struct session_state *state = ssh->state;
1083296781Sdes	u_int32_t out_blocks;
1084296781Sdes
1085296781Sdes	/* XXX client can't cope with rekeying pre-auth */
1086296781Sdes	if (!state->after_authentication)
1087296781Sdes		return 0;
1088296781Sdes
1089296781Sdes	/* Haven't keyed yet or KEX in progress. */
1090296781Sdes	if (ssh->kex == NULL || ssh_packet_is_rekeying(ssh))
1091296781Sdes		return 0;
1092296781Sdes
1093296781Sdes	/* Peer can't rekey */
1094296781Sdes	if (ssh->compat & SSH_BUG_NOREKEY)
1095296781Sdes		return 0;
1096296781Sdes
1097296781Sdes	/*
1098296781Sdes	 * Permit one packet in or out per rekey - this allows us to
1099296781Sdes	 * make progress when rekey limits are very small.
1100296781Sdes	 */
1101296781Sdes	if (state->p_send.packets == 0 && state->p_read.packets == 0)
1102296781Sdes		return 0;
1103296781Sdes
1104296781Sdes	/* Time-based rekeying */
1105296781Sdes	if (state->rekey_interval != 0 &&
1106296781Sdes	    state->rekey_time + state->rekey_interval <= monotime())
1107296781Sdes		return 1;
1108296781Sdes
1109296781Sdes	/* Always rekey when MAX_PACKETS sent in either direction */
1110296781Sdes	if (state->p_send.packets > MAX_PACKETS ||
1111296781Sdes	    state->p_read.packets > MAX_PACKETS)
1112296781Sdes		return 1;
1113296781Sdes
1114296781Sdes	/* Rekey after (cipher-specific) maxiumum blocks */
1115296781Sdes	out_blocks = roundup(outbound_packet_len,
1116296781Sdes	    state->newkeys[MODE_OUT]->enc.block_size);
1117296781Sdes	return (state->max_blocks_out &&
1118296781Sdes	    (state->p_send.blocks + out_blocks > state->max_blocks_out)) ||
1119296781Sdes	    (state->max_blocks_in &&
1120296781Sdes	    (state->p_read.blocks > state->max_blocks_in));
1121296781Sdes}
1122296781Sdes
112357429Smarkm/*
1124149749Sdes * Delayed compression for SSH2 is enabled after authentication:
1125162852Sdes * This happens on the server side after a SSH2_MSG_USERAUTH_SUCCESS is sent,
1126149749Sdes * and on the client side after a SSH2_MSG_USERAUTH_SUCCESS is received.
1127149749Sdes */
1128295367Sdesstatic int
1129295367Sdesssh_packet_enable_delayed_compress(struct ssh *ssh)
1130149749Sdes{
1131295367Sdes	struct session_state *state = ssh->state;
1132295367Sdes	struct sshcomp *comp = NULL;
1133295367Sdes	int r, mode;
1134149749Sdes
1135149749Sdes	/*
1136149749Sdes	 * Remember that we are past the authentication step, so rekeying
1137149749Sdes	 * with COMP_DELAYED will turn on compression immediately.
1138149749Sdes	 */
1139295367Sdes	state->after_authentication = 1;
1140149749Sdes	for (mode = 0; mode < MODE_MAX; mode++) {
1141162852Sdes		/* protocol error: USERAUTH_SUCCESS received before NEWKEYS */
1142295367Sdes		if (state->newkeys[mode] == NULL)
1143162852Sdes			continue;
1144295367Sdes		comp = &state->newkeys[mode]->comp;
1145149749Sdes		if (comp && !comp->enabled && comp->type == COMP_DELAYED) {
1146295367Sdes			if ((r = ssh_packet_init_compression(ssh)) != 0)
1147295367Sdes				return r;
1148295367Sdes			if (mode == MODE_OUT) {
1149295367Sdes				if ((r = start_compression_out(ssh, 6)) != 0)
1150295367Sdes					return r;
1151295367Sdes			} else {
1152295367Sdes				if ((r = start_compression_in(ssh)) != 0)
1153295367Sdes					return r;
1154295367Sdes			}
1155149749Sdes			comp->enabled = 1;
1156149749Sdes		}
1157149749Sdes	}
1158295367Sdes	return 0;
1159149749Sdes}
1160149749Sdes
1161296781Sdes/* Used to mute debug logging for noisy packet types */
1162296781Sdesstatic int
1163296781Sdesssh_packet_log_type(u_char type)
1164296781Sdes{
1165296781Sdes	switch (type) {
1166296781Sdes	case SSH2_MSG_CHANNEL_DATA:
1167296781Sdes	case SSH2_MSG_CHANNEL_EXTENDED_DATA:
1168296781Sdes	case SSH2_MSG_CHANNEL_WINDOW_ADJUST:
1169296781Sdes		return 0;
1170296781Sdes	default:
1171296781Sdes		return 1;
1172296781Sdes	}
1173296781Sdes}
1174296781Sdes
1175149749Sdes/*
117660573Skris * Finalize packet in SSH2 format (compress, mac, encrypt, enqueue)
117760573Skris */
1178295367Sdesint
1179295367Sdesssh_packet_send2_wrapped(struct ssh *ssh)
118060573Skris{
1181295367Sdes	struct session_state *state = ssh->state;
1182295367Sdes	u_char type, *cp, macbuf[SSH_DIGEST_MAX_LENGTH];
1183323124Sdes	u_char tmp, padlen, pad = 0;
1184295367Sdes	u_int authlen = 0, aadlen = 0;
1185295367Sdes	u_int len;
1186295367Sdes	struct sshenc *enc   = NULL;
1187295367Sdes	struct sshmac *mac   = NULL;
1188295367Sdes	struct sshcomp *comp = NULL;
1189295367Sdes	int r, block_size;
119060573Skris
1191295367Sdes	if (state->newkeys[MODE_OUT] != NULL) {
1192295367Sdes		enc  = &state->newkeys[MODE_OUT]->enc;
1193295367Sdes		mac  = &state->newkeys[MODE_OUT]->mac;
1194295367Sdes		comp = &state->newkeys[MODE_OUT]->comp;
1195248619Sdes		/* disable mac for authenticated encryption */
1196248619Sdes		if ((authlen = cipher_authlen(enc->cipher)) != 0)
1197248619Sdes			mac = NULL;
119860573Skris	}
119992555Sdes	block_size = enc ? enc->block_size : 8;
1200248619Sdes	aadlen = (mac && mac->enabled && mac->etm) || authlen ? 4 : 0;
120160573Skris
1202295367Sdes	type = (sshbuf_ptr(state->outgoing_packet))[5];
1203296781Sdes	if (ssh_packet_log_type(type))
1204296781Sdes		debug3("send packet: type %u", type);
120560573Skris#ifdef PACKET_DEBUG
120660573Skris	fprintf(stderr, "plain:     ");
1207295367Sdes	sshbuf_dump(state->outgoing_packet, stderr);
120860573Skris#endif
120960573Skris
121060573Skris	if (comp && comp->enabled) {
1211295367Sdes		len = sshbuf_len(state->outgoing_packet);
121260573Skris		/* skip header, compress only payload */
1213295367Sdes		if ((r = sshbuf_consume(state->outgoing_packet, 5)) != 0)
1214295367Sdes			goto out;
1215295367Sdes		sshbuf_reset(state->compression_buffer);
1216295367Sdes		if ((r = compress_buffer(ssh, state->outgoing_packet,
1217295367Sdes		    state->compression_buffer)) != 0)
1218295367Sdes			goto out;
1219295367Sdes		sshbuf_reset(state->outgoing_packet);
1220295367Sdes		if ((r = sshbuf_put(state->outgoing_packet,
1221295367Sdes		    "\0\0\0\0\0", 5)) != 0 ||
1222295367Sdes		    (r = sshbuf_putb(state->outgoing_packet,
1223295367Sdes		    state->compression_buffer)) != 0)
1224295367Sdes			goto out;
1225295367Sdes		DBG(debug("compression: raw %d compressed %zd", len,
1226295367Sdes		    sshbuf_len(state->outgoing_packet)));
122760573Skris	}
122860573Skris
122960573Skris	/* sizeof (packet_len + pad_len + payload) */
1230295367Sdes	len = sshbuf_len(state->outgoing_packet);
123160573Skris
123260573Skris	/*
123360573Skris	 * calc size of padding, alloc space, get random data,
123460573Skris	 * minimum padding is 4 bytes
123560573Skris	 */
1236248619Sdes	len -= aadlen; /* packet length is not encrypted for EtM modes */
123760573Skris	padlen = block_size - (len % block_size);
123860573Skris	if (padlen < 4)
123960573Skris		padlen += block_size;
1240295367Sdes	if (state->extra_pad) {
1241323124Sdes		tmp = state->extra_pad;
1242295367Sdes		state->extra_pad =
1243295367Sdes		    roundup(state->extra_pad, block_size);
1244323124Sdes		/* check if roundup overflowed */
1245323124Sdes		if (state->extra_pad < tmp)
1246323124Sdes			return SSH_ERR_INVALID_ARGUMENT;
1247323124Sdes		tmp = (len + padlen) % state->extra_pad;
1248323124Sdes		/* Check whether pad calculation below will underflow */
1249323124Sdes		if (tmp > state->extra_pad)
1250323124Sdes			return SSH_ERR_INVALID_ARGUMENT;
1251323124Sdes		pad = state->extra_pad - tmp;
1252295367Sdes		DBG(debug3("%s: adding %d (len %d padlen %d extra_pad %d)",
1253295367Sdes		    __func__, pad, len, padlen, state->extra_pad));
1254323124Sdes		tmp = padlen;
125592555Sdes		padlen += pad;
1256323124Sdes		/* Check whether padlen calculation overflowed */
1257323124Sdes		if (padlen < tmp)
1258323124Sdes			return SSH_ERR_INVALID_ARGUMENT; /* overflow */
1259295367Sdes		state->extra_pad = 0;
126092555Sdes	}
1261295367Sdes	if ((r = sshbuf_reserve(state->outgoing_packet, padlen, &cp)) != 0)
1262295367Sdes		goto out;
1263295367Sdes	if (enc && !state->send_context.plaintext) {
126460573Skris		/* random padding */
1265295367Sdes		arc4random_buf(cp, padlen);
126660573Skris	} else {
126760573Skris		/* clear padding */
1268264377Sdes		explicit_bzero(cp, padlen);
126960573Skris	}
1270248619Sdes	/* sizeof (packet_len + pad_len + payload + padding) */
1271295367Sdes	len = sshbuf_len(state->outgoing_packet);
1272295367Sdes	cp = sshbuf_mutable_ptr(state->outgoing_packet);
1273295367Sdes	if (cp == NULL) {
1274295367Sdes		r = SSH_ERR_INTERNAL_ERROR;
1275295367Sdes		goto out;
1276295367Sdes	}
127760573Skris	/* packet_length includes payload, padding and padding length field */
1278295367Sdes	POKE_U32(cp, len - 4);
127992555Sdes	cp[4] = padlen;
1280248619Sdes	DBG(debug("send: len %d (includes padlen %d, aadlen %d)",
1281248619Sdes	    len, padlen, aadlen));
128260573Skris
128360573Skris	/* compute MAC over seqnr and packet(length fields, payload, padding) */
1284248619Sdes	if (mac && mac->enabled && !mac->etm) {
1285295367Sdes		if ((r = mac_compute(mac, state->p_send.seqnr,
1286295367Sdes		    sshbuf_ptr(state->outgoing_packet), len,
1287295367Sdes		    macbuf, sizeof(macbuf))) != 0)
1288295367Sdes			goto out;
1289295367Sdes		DBG(debug("done calc MAC out #%d", state->p_send.seqnr));
129060573Skris	}
129160573Skris	/* encrypt packet and append to output buffer. */
1292295367Sdes	if ((r = sshbuf_reserve(state->output,
1293295367Sdes	    sshbuf_len(state->outgoing_packet) + authlen, &cp)) != 0)
1294295367Sdes		goto out;
1295295367Sdes	if ((r = cipher_crypt(&state->send_context, state->p_send.seqnr, cp,
1296295367Sdes	    sshbuf_ptr(state->outgoing_packet),
1297295367Sdes	    len - aadlen, aadlen, authlen)) != 0)
1298295367Sdes		goto out;
129960573Skris	/* append unencrypted MAC */
1300248619Sdes	if (mac && mac->enabled) {
1301248619Sdes		if (mac->etm) {
1302248619Sdes			/* EtM: compute mac over aadlen + cipher text */
1303295367Sdes			if ((r = mac_compute(mac, state->p_send.seqnr,
1304295367Sdes			    cp, len, macbuf, sizeof(macbuf))) != 0)
1305295367Sdes				goto out;
1306248619Sdes			DBG(debug("done calc MAC(EtM) out #%d",
1307295367Sdes			    state->p_send.seqnr));
1308248619Sdes		}
1309295367Sdes		if ((r = sshbuf_put(state->output, macbuf, mac->mac_len)) != 0)
1310295367Sdes			goto out;
1311248619Sdes	}
131260573Skris#ifdef PACKET_DEBUG
131360573Skris	fprintf(stderr, "encrypted: ");
1314295367Sdes	sshbuf_dump(state->output, stderr);
131560573Skris#endif
131660573Skris	/* increment sequence number for outgoing packets */
1317295367Sdes	if (++state->p_send.seqnr == 0)
1318124208Sdes		logit("outgoing seqnr wraps around");
1319295367Sdes	if (++state->p_send.packets == 0)
1320295367Sdes		if (!(ssh->compat & SSH_BUG_NOREKEY))
1321295367Sdes			return SSH_ERR_NEED_REKEY;
1322295367Sdes	state->p_send.blocks += len / block_size;
1323295367Sdes	state->p_send.bytes += len;
1324295367Sdes	sshbuf_reset(state->outgoing_packet);
132560573Skris
132676259Sgreen	if (type == SSH2_MSG_NEWKEYS)
1327295367Sdes		r = ssh_set_newkeys(ssh, MODE_OUT);
1328295367Sdes	else if (type == SSH2_MSG_USERAUTH_SUCCESS && state->server_side)
1329295367Sdes		r = ssh_packet_enable_delayed_compress(ssh);
1330295367Sdes	else
1331295367Sdes		r = 0;
1332295367Sdes out:
1333295367Sdes	return r;
133460573Skris}
133560573Skris
1336296781Sdes/* returns non-zero if the specified packet type is usec by KEX */
1337296781Sdesstatic int
1338296781Sdesssh_packet_type_is_kex(u_char type)
1339296781Sdes{
1340296781Sdes	return
1341296781Sdes	    type >= SSH2_MSG_TRANSPORT_MIN &&
1342296781Sdes	    type <= SSH2_MSG_TRANSPORT_MAX &&
1343296781Sdes	    type != SSH2_MSG_SERVICE_REQUEST &&
1344296781Sdes	    type != SSH2_MSG_SERVICE_ACCEPT &&
1345296781Sdes	    type != SSH2_MSG_EXT_INFO;
1346296781Sdes}
1347296781Sdes
1348295367Sdesint
1349295367Sdesssh_packet_send2(struct ssh *ssh)
1350124208Sdes{
1351295367Sdes	struct session_state *state = ssh->state;
1352124208Sdes	struct packet *p;
1353295367Sdes	u_char type;
1354296781Sdes	int r, need_rekey;
1355124208Sdes
1356296781Sdes	if (sshbuf_len(state->outgoing_packet) < 6)
1357296781Sdes		return SSH_ERR_INTERNAL_ERROR;
1358295367Sdes	type = sshbuf_ptr(state->outgoing_packet)[5];
1359296781Sdes	need_rekey = !ssh_packet_type_is_kex(type) &&
1360296781Sdes	    ssh_packet_need_rekeying(ssh, sshbuf_len(state->outgoing_packet));
1361124208Sdes
1362296781Sdes	/*
1363296781Sdes	 * During rekeying we can only send key exchange messages.
1364296781Sdes	 * Queue everything else.
1365296781Sdes	 */
1366296781Sdes	if ((need_rekey || state->rekeying) && !ssh_packet_type_is_kex(type)) {
1367296781Sdes		if (need_rekey)
1368296781Sdes			debug3("%s: rekex triggered", __func__);
1369296781Sdes		debug("enqueue packet: %u", type);
1370296781Sdes		p = calloc(1, sizeof(*p));
1371296781Sdes		if (p == NULL)
1372296781Sdes			return SSH_ERR_ALLOC_FAIL;
1373296781Sdes		p->type = type;
1374296781Sdes		p->payload = state->outgoing_packet;
1375296781Sdes		TAILQ_INSERT_TAIL(&state->outgoing, p, next);
1376296781Sdes		state->outgoing_packet = sshbuf_new();
1377296781Sdes		if (state->outgoing_packet == NULL)
1378296781Sdes			return SSH_ERR_ALLOC_FAIL;
1379296781Sdes		if (need_rekey) {
1380296781Sdes			/*
1381296781Sdes			 * This packet triggered a rekey, so send the
1382296781Sdes			 * KEXINIT now.
1383296781Sdes			 * NB. reenters this function via kex_start_rekex().
1384296781Sdes			 */
1385296781Sdes			return kex_start_rekex(ssh);
1386124208Sdes		}
1387296781Sdes		return 0;
1388124208Sdes	}
1389124208Sdes
1390124208Sdes	/* rekeying starts with sending KEXINIT */
1391124208Sdes	if (type == SSH2_MSG_KEXINIT)
1392295367Sdes		state->rekeying = 1;
1393124208Sdes
1394295367Sdes	if ((r = ssh_packet_send2_wrapped(ssh)) != 0)
1395295367Sdes		return r;
1396124208Sdes
1397124208Sdes	/* after a NEWKEYS message we can send the complete queue */
1398124208Sdes	if (type == SSH2_MSG_NEWKEYS) {
1399295367Sdes		state->rekeying = 0;
1400295367Sdes		state->rekey_time = monotime();
1401295367Sdes		while ((p = TAILQ_FIRST(&state->outgoing))) {
1402124208Sdes			type = p->type;
1403296781Sdes			/*
1404296781Sdes			 * If this packet triggers a rekex, then skip the
1405296781Sdes			 * remaining packets in the queue for now.
1406296781Sdes			 * NB. re-enters this function via kex_start_rekex.
1407296781Sdes			 */
1408296781Sdes			if (ssh_packet_need_rekeying(ssh,
1409296781Sdes			    sshbuf_len(p->payload))) {
1410296781Sdes				debug3("%s: queued packet triggered rekex",
1411296781Sdes				    __func__);
1412296781Sdes				return kex_start_rekex(ssh);
1413296781Sdes			}
1414124208Sdes			debug("dequeue packet: %u", type);
1415295367Sdes			sshbuf_free(state->outgoing_packet);
1416295367Sdes			state->outgoing_packet = p->payload;
1417295367Sdes			TAILQ_REMOVE(&state->outgoing, p, next);
1418296781Sdes			memset(p, 0, sizeof(*p));
1419255767Sdes			free(p);
1420295367Sdes			if ((r = ssh_packet_send2_wrapped(ssh)) != 0)
1421295367Sdes				return r;
1422124208Sdes		}
1423124208Sdes	}
1424295367Sdes	return 0;
1425124208Sdes}
1426124208Sdes
142760573Skris/*
142857429Smarkm * Waits until a packet has been received, and returns its type.  Note that
142957429Smarkm * no other data is processed until this returns, so this function should not
143057429Smarkm * be used during the interactive session.
143157429Smarkm */
143257429Smarkm
143357429Smarkmint
1434295367Sdesssh_packet_read_seqnr(struct ssh *ssh, u_char *typep, u_int32_t *seqnr_p)
143557429Smarkm{
1436295367Sdes	struct session_state *state = ssh->state;
1437296781Sdes	int len, r, ms_remain;
143876259Sgreen	fd_set *setp;
143957429Smarkm	char buf[8192];
1440181111Sdes	struct timeval timeout, start, *timeoutp = NULL;
1441181111Sdes
144260573Skris	DBG(debug("packet_read()"));
144357429Smarkm
1444295367Sdes	setp = calloc(howmany(state->connection_in + 1,
1445197679Sdes	    NFDBITS), sizeof(fd_mask));
1446295367Sdes	if (setp == NULL)
1447295367Sdes		return SSH_ERR_ALLOC_FAIL;
144876259Sgreen
1449295367Sdes	/*
1450295367Sdes	 * Since we are blocking, ensure that all written packets have
1451295367Sdes	 * been sent.
1452295367Sdes	 */
1453295367Sdes	if ((r = ssh_packet_write_wait(ssh)) != 0)
1454295367Sdes		goto out;
145557429Smarkm
145657429Smarkm	/* Stay in the loop until we have received a complete packet. */
145757429Smarkm	for (;;) {
145857429Smarkm		/* Try to read a packet from the buffer. */
1459295367Sdes		r = ssh_packet_read_poll_seqnr(ssh, typep, seqnr_p);
1460295367Sdes		if (r != 0)
1461295367Sdes			break;
146292555Sdes		if (!compat20 && (
1463295367Sdes		    *typep == SSH_SMSG_SUCCESS
1464295367Sdes		    || *typep == SSH_SMSG_FAILURE
1465295367Sdes		    || *typep == SSH_CMSG_EOF
1466295367Sdes		    || *typep == SSH_CMSG_EXIT_CONFIRMATION))
1467295367Sdes			if ((r = sshpkt_get_end(ssh)) != 0)
1468295367Sdes				break;
146957429Smarkm		/* If we got a packet, return it. */
1470295367Sdes		if (*typep != SSH_MSG_NONE)
1471295367Sdes			break;
147257429Smarkm		/*
147357429Smarkm		 * Otherwise, wait for some data to arrive, add it to the
147457429Smarkm		 * buffer, and try again.
147557429Smarkm		 */
1476295367Sdes		memset(setp, 0, howmany(state->connection_in + 1,
1477197679Sdes		    NFDBITS) * sizeof(fd_mask));
1478295367Sdes		FD_SET(state->connection_in, setp);
147957429Smarkm
1480295367Sdes		if (state->packet_timeout_ms > 0) {
1481295367Sdes			ms_remain = state->packet_timeout_ms;
1482181111Sdes			timeoutp = &timeout;
1483181111Sdes		}
148457429Smarkm		/* Wait for some data to arrive. */
1485181111Sdes		for (;;) {
1486295367Sdes			if (state->packet_timeout_ms != -1) {
1487181111Sdes				ms_to_timeval(&timeout, ms_remain);
1488181111Sdes				gettimeofday(&start, NULL);
1489181111Sdes			}
1490295367Sdes			if ((r = select(state->connection_in + 1, setp,
1491197679Sdes			    NULL, NULL, timeoutp)) >= 0)
1492181111Sdes				break;
1493197679Sdes			if (errno != EAGAIN && errno != EINTR &&
1494181111Sdes			    errno != EWOULDBLOCK)
1495181111Sdes				break;
1496295367Sdes			if (state->packet_timeout_ms == -1)
1497181111Sdes				continue;
1498181111Sdes			ms_subtract_diff(&start, &ms_remain);
1499181111Sdes			if (ms_remain <= 0) {
1500295367Sdes				r = 0;
1501181111Sdes				break;
1502181111Sdes			}
1503181111Sdes		}
1504295367Sdes		if (r == 0)
1505295367Sdes			return SSH_ERR_CONN_TIMEOUT;
150657429Smarkm		/* Read data from the socket. */
1507296781Sdes		len = read(state->connection_in, buf, sizeof(buf));
150857429Smarkm		if (len == 0) {
1509295367Sdes			r = SSH_ERR_CONN_CLOSED;
1510295367Sdes			goto out;
151157429Smarkm		}
1512295367Sdes		if (len < 0) {
1513295367Sdes			r = SSH_ERR_SYSTEM_ERROR;
1514295367Sdes			goto out;
1515295367Sdes		}
1516295367Sdes
151757429Smarkm		/* Append it to the buffer. */
1518295367Sdes		if ((r = ssh_packet_process_incoming(ssh, buf, len)) != 0)
1519295367Sdes			goto out;
152057429Smarkm	}
1521295367Sdes out:
1522295367Sdes	free(setp);
1523295367Sdes	return r;
152457429Smarkm}
152557429Smarkm
152692555Sdesint
1527295367Sdesssh_packet_read(struct ssh *ssh)
152892555Sdes{
1529295367Sdes	u_char type;
1530295367Sdes	int r;
1531295367Sdes
1532295367Sdes	if ((r = ssh_packet_read_seqnr(ssh, &type, NULL)) != 0)
1533295367Sdes		fatal("%s: %s", __func__, ssh_err(r));
1534295367Sdes	return type;
153592555Sdes}
153692555Sdes
153757429Smarkm/*
153857429Smarkm * Waits until a packet has been received, verifies that its type matches
153957429Smarkm * that given, and gives a fatal error and exits if there is a mismatch.
154057429Smarkm */
154157429Smarkm
1542295367Sdesint
1543295367Sdesssh_packet_read_expect(struct ssh *ssh, u_int expected_type)
154457429Smarkm{
1545295367Sdes	int r;
1546295367Sdes	u_char type;
154757429Smarkm
1548295367Sdes	if ((r = ssh_packet_read_seqnr(ssh, &type, NULL)) != 0)
1549295367Sdes		return r;
1550295367Sdes	if (type != expected_type) {
1551295367Sdes		if ((r = sshpkt_disconnect(ssh,
1552295367Sdes		    "Protocol error: expected packet type %d, got %d",
1553295367Sdes		    expected_type, type)) != 0)
1554295367Sdes			return r;
1555295367Sdes		return SSH_ERR_PROTOCOL_ERROR;
1556295367Sdes	}
1557295367Sdes	return 0;
155857429Smarkm}
155957429Smarkm
156057429Smarkm/* Checks if a full packet is available in the data received so far via
156157429Smarkm * packet_process_incoming.  If so, reads the packet; otherwise returns
156257429Smarkm * SSH_MSG_NONE.  This does not wait for data from the connection.
156357429Smarkm *
156457429Smarkm * SSH_MSG_DISCONNECT is handled specially here.  Also,
156557429Smarkm * SSH_MSG_IGNORE messages are skipped by this function and are never returned
156657429Smarkm * to higher levels.
156757429Smarkm */
156857429Smarkm
1569295367Sdesint
1570295367Sdesssh_packet_read_poll1(struct ssh *ssh, u_char *typep)
157157429Smarkm{
1572295367Sdes	struct session_state *state = ssh->state;
157376259Sgreen	u_int len, padded_len;
1574295367Sdes	const char *emsg;
1575295367Sdes	const u_char *cp;
1576295367Sdes	u_char *p;
157776259Sgreen	u_int checksum, stored_checksum;
1578295367Sdes	int r;
157957429Smarkm
1580295367Sdes	*typep = SSH_MSG_NONE;
1581295367Sdes
158257429Smarkm	/* Check if input size is less than minimum packet size. */
1583295367Sdes	if (sshbuf_len(state->input) < 4 + 8)
1584295367Sdes		return 0;
158557429Smarkm	/* Get length of incoming packet. */
1586295367Sdes	len = PEEK_U32(sshbuf_ptr(state->input));
1587295367Sdes	if (len < 1 + 2 + 2 || len > 256 * 1024) {
1588295367Sdes		if ((r = sshpkt_disconnect(ssh, "Bad packet length %u",
1589295367Sdes		    len)) != 0)
1590295367Sdes			return r;
1591295367Sdes		return SSH_ERR_CONN_CORRUPT;
1592295367Sdes	}
159357429Smarkm	padded_len = (len + 8) & ~7;
159457429Smarkm
159557429Smarkm	/* Check if the packet has been entirely received. */
1596295367Sdes	if (sshbuf_len(state->input) < 4 + padded_len)
1597295367Sdes		return 0;
159857429Smarkm
159957429Smarkm	/* The entire packet is in buffer. */
160057429Smarkm
160157429Smarkm	/* Consume packet length. */
1602295367Sdes	if ((r = sshbuf_consume(state->input, 4)) != 0)
1603295367Sdes		goto out;
160457429Smarkm
160592555Sdes	/*
160692555Sdes	 * Cryptographic attack detector for ssh
160792555Sdes	 * (C)1998 CORE-SDI, Buenos Aires Argentina
160892555Sdes	 * Ariel Futoransky(futo@core-sdi.com)
160992555Sdes	 */
1610295367Sdes	if (!state->receive_context.plaintext) {
1611295367Sdes		emsg = NULL;
1612295367Sdes		switch (detect_attack(&state->deattack,
1613295367Sdes		    sshbuf_ptr(state->input), padded_len)) {
1614295367Sdes		case DEATTACK_OK:
1615295367Sdes			break;
1616162852Sdes		case DEATTACK_DETECTED:
1617295367Sdes			emsg = "crc32 compensation attack detected";
1618295367Sdes			break;
1619162852Sdes		case DEATTACK_DOS_DETECTED:
1620295367Sdes			emsg = "deattack denial of service detected";
1621295367Sdes			break;
1622295367Sdes		default:
1623295367Sdes			emsg = "deattack error";
1624295367Sdes			break;
1625162852Sdes		}
1626295367Sdes		if (emsg != NULL) {
1627295367Sdes			error("%s", emsg);
1628295367Sdes			if ((r = sshpkt_disconnect(ssh, "%s", emsg)) != 0 ||
1629295367Sdes			    (r = ssh_packet_write_wait(ssh)) != 0)
1630295367Sdes					return r;
1631295367Sdes			return SSH_ERR_CONN_CORRUPT;
1632295367Sdes		}
1633162852Sdes	}
163492555Sdes
163592555Sdes	/* Decrypt data to incoming_packet. */
1636295367Sdes	sshbuf_reset(state->incoming_packet);
1637295367Sdes	if ((r = sshbuf_reserve(state->incoming_packet, padded_len, &p)) != 0)
1638295367Sdes		goto out;
1639295367Sdes	if ((r = cipher_crypt(&state->receive_context, 0, p,
1640295367Sdes	    sshbuf_ptr(state->input), padded_len, 0, 0)) != 0)
1641295367Sdes		goto out;
164292555Sdes
1643295367Sdes	if ((r = sshbuf_consume(state->input, padded_len)) != 0)
1644295367Sdes		goto out;
164557429Smarkm
164657429Smarkm#ifdef PACKET_DEBUG
164757429Smarkm	fprintf(stderr, "read_poll plain: ");
1648295367Sdes	sshbuf_dump(state->incoming_packet, stderr);
164957429Smarkm#endif
165057429Smarkm
165157429Smarkm	/* Compute packet checksum. */
1652295367Sdes	checksum = ssh_crc32(sshbuf_ptr(state->incoming_packet),
1653295367Sdes	    sshbuf_len(state->incoming_packet) - 4);
165457429Smarkm
165557429Smarkm	/* Skip padding. */
1656295367Sdes	if ((r = sshbuf_consume(state->incoming_packet, 8 - len % 8)) != 0)
1657295367Sdes		goto out;
165857429Smarkm
165957429Smarkm	/* Test check bytes. */
1660295367Sdes	if (len != sshbuf_len(state->incoming_packet)) {
1661295367Sdes		error("%s: len %d != sshbuf_len %zd", __func__,
1662295367Sdes		    len, sshbuf_len(state->incoming_packet));
1663295367Sdes		if ((r = sshpkt_disconnect(ssh, "invalid packet length")) != 0 ||
1664295367Sdes		    (r = ssh_packet_write_wait(ssh)) != 0)
1665295367Sdes			return r;
1666295367Sdes		return SSH_ERR_CONN_CORRUPT;
1667295367Sdes	}
166857429Smarkm
1669295367Sdes	cp = sshbuf_ptr(state->incoming_packet) + len - 4;
1670295367Sdes	stored_checksum = PEEK_U32(cp);
1671295367Sdes	if (checksum != stored_checksum) {
1672295367Sdes		error("Corrupted check bytes on input");
1673295367Sdes		if ((r = sshpkt_disconnect(ssh, "connection corrupted")) != 0 ||
1674295367Sdes		    (r = ssh_packet_write_wait(ssh)) != 0)
1675295367Sdes			return r;
1676295367Sdes		return SSH_ERR_CONN_CORRUPT;
1677295367Sdes	}
1678295367Sdes	if ((r = sshbuf_consume_end(state->incoming_packet, 4)) < 0)
1679295367Sdes		goto out;
168057429Smarkm
1681295367Sdes	if (state->packet_compression) {
1682295367Sdes		sshbuf_reset(state->compression_buffer);
1683295367Sdes		if ((r = uncompress_buffer(ssh, state->incoming_packet,
1684295367Sdes		    state->compression_buffer)) != 0)
1685295367Sdes			goto out;
1686295367Sdes		sshbuf_reset(state->incoming_packet);
1687295367Sdes		if ((r = sshbuf_putb(state->incoming_packet,
1688295367Sdes		    state->compression_buffer)) != 0)
1689295367Sdes			goto out;
169057429Smarkm	}
1691295367Sdes	state->p_read.packets++;
1692295367Sdes	state->p_read.bytes += padded_len + 4;
1693295367Sdes	if ((r = sshbuf_get_u8(state->incoming_packet, typep)) != 0)
1694295367Sdes		goto out;
1695295367Sdes	if (*typep < SSH_MSG_MIN || *typep > SSH_MSG_MAX) {
1696295367Sdes		error("Invalid ssh1 packet type: %d", *typep);
1697295367Sdes		if ((r = sshpkt_disconnect(ssh, "invalid packet type")) != 0 ||
1698295367Sdes		    (r = ssh_packet_write_wait(ssh)) != 0)
1699295367Sdes			return r;
1700295367Sdes		return SSH_ERR_PROTOCOL_ERROR;
1701295367Sdes	}
1702295367Sdes	r = 0;
1703295367Sdes out:
1704295367Sdes	return r;
170560573Skris}
170657429Smarkm
1707295367Sdesint
1708295367Sdesssh_packet_read_poll2(struct ssh *ssh, u_char *typep, u_int32_t *seqnr_p)
170960573Skris{
1710295367Sdes	struct session_state *state = ssh->state;
171176259Sgreen	u_int padlen, need;
1712323124Sdes	u_char *cp;
1713295367Sdes	u_int maclen, aadlen = 0, authlen = 0, block_size;
1714295367Sdes	struct sshenc *enc   = NULL;
1715295367Sdes	struct sshmac *mac   = NULL;
1716295367Sdes	struct sshcomp *comp = NULL;
1717295367Sdes	int r;
171857429Smarkm
1719295367Sdes	*typep = SSH_MSG_NONE;
1720192595Sdes
1721295367Sdes	if (state->packet_discard)
1722295367Sdes		return 0;
1723295367Sdes
1724295367Sdes	if (state->newkeys[MODE_IN] != NULL) {
1725295367Sdes		enc  = &state->newkeys[MODE_IN]->enc;
1726295367Sdes		mac  = &state->newkeys[MODE_IN]->mac;
1727295367Sdes		comp = &state->newkeys[MODE_IN]->comp;
1728248619Sdes		/* disable mac for authenticated encryption */
1729248619Sdes		if ((authlen = cipher_authlen(enc->cipher)) != 0)
1730248619Sdes			mac = NULL;
173157429Smarkm	}
173260573Skris	maclen = mac && mac->enabled ? mac->mac_len : 0;
173392555Sdes	block_size = enc ? enc->block_size : 8;
1734248619Sdes	aadlen = (mac && mac->enabled && mac->etm) || authlen ? 4 : 0;
173560573Skris
1736295367Sdes	if (aadlen && state->packlen == 0) {
1737295367Sdes		if (cipher_get_length(&state->receive_context,
1738295367Sdes		    &state->packlen, state->p_read.seqnr,
1739295367Sdes		    sshbuf_ptr(state->input), sshbuf_len(state->input)) != 0)
1740295367Sdes			return 0;
1741295367Sdes		if (state->packlen < 1 + 4 ||
1742295367Sdes		    state->packlen > PACKET_MAX_SIZE) {
1743248619Sdes#ifdef PACKET_DEBUG
1744295367Sdes			sshbuf_dump(state->input, stderr);
1745248619Sdes#endif
1746295367Sdes			logit("Bad packet length %u.", state->packlen);
1747295367Sdes			if ((r = sshpkt_disconnect(ssh, "Packet corrupt")) != 0)
1748295367Sdes				return r;
1749295367Sdes			return SSH_ERR_CONN_CORRUPT;
1750248619Sdes		}
1751295367Sdes		sshbuf_reset(state->incoming_packet);
1752295367Sdes	} else if (state->packlen == 0) {
175360573Skris		/*
175460573Skris		 * check if input size is less than the cipher block size,
175560573Skris		 * decrypt first block and extract length of incoming packet
175660573Skris		 */
1757295367Sdes		if (sshbuf_len(state->input) < block_size)
1758295367Sdes			return 0;
1759295367Sdes		sshbuf_reset(state->incoming_packet);
1760295367Sdes		if ((r = sshbuf_reserve(state->incoming_packet, block_size,
1761295367Sdes		    &cp)) != 0)
1762295367Sdes			goto out;
1763295367Sdes		if ((r = cipher_crypt(&state->receive_context,
1764295367Sdes		    state->p_send.seqnr, cp, sshbuf_ptr(state->input),
1765295367Sdes		    block_size, 0, 0)) != 0)
1766295367Sdes			goto out;
1767295367Sdes		state->packlen = PEEK_U32(sshbuf_ptr(state->incoming_packet));
1768295367Sdes		if (state->packlen < 1 + 4 ||
1769295367Sdes		    state->packlen > PACKET_MAX_SIZE) {
1770124208Sdes#ifdef PACKET_DEBUG
1771295367Sdes			fprintf(stderr, "input: \n");
1772295367Sdes			sshbuf_dump(state->input, stderr);
1773295367Sdes			fprintf(stderr, "incoming_packet: \n");
1774295367Sdes			sshbuf_dump(state->incoming_packet, stderr);
1775124208Sdes#endif
1776295367Sdes			logit("Bad packet length %u.", state->packlen);
1777323124Sdes			return ssh_packet_start_discard(ssh, enc, mac, 0,
1778323124Sdes			    PACKET_MAX_SIZE);
177960573Skris		}
1780295367Sdes		if ((r = sshbuf_consume(state->input, block_size)) != 0)
1781295367Sdes			goto out;
178260573Skris	}
1783295367Sdes	DBG(debug("input: packet len %u", state->packlen+4));
1784295367Sdes
1785248619Sdes	if (aadlen) {
1786248619Sdes		/* only the payload is encrypted */
1787295367Sdes		need = state->packlen;
1788248619Sdes	} else {
1789248619Sdes		/*
1790248619Sdes		 * the payload size and the payload are encrypted, but we
1791248619Sdes		 * have a partial packet of block_size bytes
1792248619Sdes		 */
1793295367Sdes		need = 4 + state->packlen - block_size;
1794248619Sdes	}
1795248619Sdes	DBG(debug("partial packet: block %d, need %d, maclen %d, authlen %d,"
1796248619Sdes	    " aadlen %d", block_size, need, maclen, authlen, aadlen));
1797192595Sdes	if (need % block_size != 0) {
1798192595Sdes		logit("padding error: need %d block %d mod %d",
179960573Skris		    need, block_size, need % block_size);
1800323124Sdes		return ssh_packet_start_discard(ssh, enc, mac, 0,
1801323124Sdes		    PACKET_MAX_SIZE - block_size);
1802192595Sdes	}
180360573Skris	/*
180460573Skris	 * check if the entire packet has been received and
1805248619Sdes	 * decrypt into incoming_packet:
1806248619Sdes	 * 'aadlen' bytes are unencrypted, but authenticated.
1807248619Sdes	 * 'need' bytes are encrypted, followed by either
1808248619Sdes	 * 'authlen' bytes of authentication tag or
1809248619Sdes	 * 'maclen' bytes of message authentication code.
181060573Skris	 */
1811295367Sdes	if (sshbuf_len(state->input) < aadlen + need + authlen + maclen)
1812323124Sdes		return 0; /* packet is incomplete */
181360573Skris#ifdef PACKET_DEBUG
181460573Skris	fprintf(stderr, "read_poll enc/full: ");
1815295367Sdes	sshbuf_dump(state->input, stderr);
181660573Skris#endif
1817323124Sdes	/* EtM: check mac over encrypted input */
1818295367Sdes	if (mac && mac->enabled && mac->etm) {
1819323124Sdes		if ((r = mac_check(mac, state->p_read.seqnr,
1820295367Sdes		    sshbuf_ptr(state->input), aadlen + need,
1821323124Sdes		    sshbuf_ptr(state->input) + aadlen + need + authlen,
1822323124Sdes		    maclen)) != 0) {
1823323124Sdes			if (r == SSH_ERR_MAC_INVALID)
1824323124Sdes				logit("Corrupted MAC on input.");
1825295367Sdes			goto out;
1826323124Sdes		}
1827295367Sdes	}
1828295367Sdes	if ((r = sshbuf_reserve(state->incoming_packet, aadlen + need,
1829295367Sdes	    &cp)) != 0)
1830295367Sdes		goto out;
1831295367Sdes	if ((r = cipher_crypt(&state->receive_context, state->p_read.seqnr, cp,
1832295367Sdes	    sshbuf_ptr(state->input), need, aadlen, authlen)) != 0)
1833295367Sdes		goto out;
1834295367Sdes	if ((r = sshbuf_consume(state->input, aadlen + need + authlen)) != 0)
1835295367Sdes		goto out;
183660573Skris	if (mac && mac->enabled) {
1837323124Sdes		/* Not EtM: check MAC over cleartext */
1838323124Sdes		if (!mac->etm && (r = mac_check(mac, state->p_read.seqnr,
1839323124Sdes		    sshbuf_ptr(state->incoming_packet),
1840323124Sdes		    sshbuf_len(state->incoming_packet),
1841323124Sdes		    sshbuf_ptr(state->input), maclen)) != 0) {
1842323124Sdes			if (r != SSH_ERR_MAC_INVALID)
1843295367Sdes				goto out;
1844192595Sdes			logit("Corrupted MAC on input.");
1845192595Sdes			if (need > PACKET_MAX_SIZE)
1846295367Sdes				return SSH_ERR_INTERNAL_ERROR;
1847295367Sdes			return ssh_packet_start_discard(ssh, enc, mac,
1848323124Sdes			    sshbuf_len(state->incoming_packet),
1849323124Sdes			    PACKET_MAX_SIZE - need);
1850192595Sdes		}
1851323124Sdes		/* Remove MAC from input buffer */
1852295367Sdes		DBG(debug("MAC #%d ok", state->p_read.seqnr));
1853295367Sdes		if ((r = sshbuf_consume(state->input, mac->mac_len)) != 0)
1854295367Sdes			goto out;
185560573Skris	}
185692555Sdes	if (seqnr_p != NULL)
1857295367Sdes		*seqnr_p = state->p_read.seqnr;
1858295367Sdes	if (++state->p_read.seqnr == 0)
1859124208Sdes		logit("incoming seqnr wraps around");
1860295367Sdes	if (++state->p_read.packets == 0)
1861295367Sdes		if (!(ssh->compat & SSH_BUG_NOREKEY))
1862295367Sdes			return SSH_ERR_NEED_REKEY;
1863295367Sdes	state->p_read.blocks += (state->packlen + 4) / block_size;
1864295367Sdes	state->p_read.bytes += state->packlen + 4;
186560573Skris
186660573Skris	/* get padlen */
1867295367Sdes	padlen = sshbuf_ptr(state->incoming_packet)[4];
186860573Skris	DBG(debug("input: padlen %d", padlen));
1869295367Sdes	if (padlen < 4)	{
1870295367Sdes		if ((r = sshpkt_disconnect(ssh,
1871295367Sdes		    "Corrupted padlen %d on input.", padlen)) != 0 ||
1872295367Sdes		    (r = ssh_packet_write_wait(ssh)) != 0)
1873295367Sdes			return r;
1874295367Sdes		return SSH_ERR_CONN_CORRUPT;
1875295367Sdes	}
187660573Skris
187760573Skris	/* skip packet size + padlen, discard padding */
1878295367Sdes	if ((r = sshbuf_consume(state->incoming_packet, 4 + 1)) != 0 ||
1879295367Sdes	    ((r = sshbuf_consume_end(state->incoming_packet, padlen)) != 0))
1880295367Sdes		goto out;
188160573Skris
1882295367Sdes	DBG(debug("input: len before de-compress %zd",
1883295367Sdes	    sshbuf_len(state->incoming_packet)));
188460573Skris	if (comp && comp->enabled) {
1885295367Sdes		sshbuf_reset(state->compression_buffer);
1886295367Sdes		if ((r = uncompress_buffer(ssh, state->incoming_packet,
1887295367Sdes		    state->compression_buffer)) != 0)
1888295367Sdes			goto out;
1889295367Sdes		sshbuf_reset(state->incoming_packet);
1890295367Sdes		if ((r = sshbuf_putb(state->incoming_packet,
1891295367Sdes		    state->compression_buffer)) != 0)
1892295367Sdes			goto out;
1893295367Sdes		DBG(debug("input: len after de-compress %zd",
1894295367Sdes		    sshbuf_len(state->incoming_packet)));
189560573Skris	}
189660573Skris	/*
189760573Skris	 * get packet type, implies consume.
189860573Skris	 * return length of payload (without type field)
189960573Skris	 */
1900295367Sdes	if ((r = sshbuf_get_u8(state->incoming_packet, typep)) != 0)
1901295367Sdes		goto out;
1902296781Sdes	if (ssh_packet_log_type(*typep))
1903296781Sdes		debug3("receive packet: type %u", *typep);
1904295367Sdes	if (*typep < SSH2_MSG_MIN || *typep >= SSH2_MSG_LOCAL_MIN) {
1905295367Sdes		if ((r = sshpkt_disconnect(ssh,
1906295367Sdes		    "Invalid ssh2 packet type: %d", *typep)) != 0 ||
1907295367Sdes		    (r = ssh_packet_write_wait(ssh)) != 0)
1908295367Sdes			return r;
1909295367Sdes		return SSH_ERR_PROTOCOL_ERROR;
1910295367Sdes	}
1911295367Sdes	if (*typep == SSH2_MSG_NEWKEYS)
1912295367Sdes		r = ssh_set_newkeys(ssh, MODE_IN);
1913295367Sdes	else if (*typep == SSH2_MSG_USERAUTH_SUCCESS && !state->server_side)
1914295367Sdes		r = ssh_packet_enable_delayed_compress(ssh);
1915295367Sdes	else
1916295367Sdes		r = 0;
191760573Skris#ifdef PACKET_DEBUG
1918295367Sdes	fprintf(stderr, "read/plain[%d]:\r\n", *typep);
1919295367Sdes	sshbuf_dump(state->incoming_packet, stderr);
192060573Skris#endif
192192555Sdes	/* reset for next packet */
1922295367Sdes	state->packlen = 0;
1923296781Sdes
1924296781Sdes	/* do we need to rekey? */
1925296781Sdes	if (ssh_packet_need_rekeying(ssh, 0)) {
1926296781Sdes		debug3("%s: rekex triggered", __func__);
1927296781Sdes		if ((r = kex_start_rekex(ssh)) != 0)
1928296781Sdes			return r;
1929296781Sdes	}
1930295367Sdes out:
1931295367Sdes	return r;
193257429Smarkm}
193357429Smarkm
193460573Skrisint
1935295367Sdesssh_packet_read_poll_seqnr(struct ssh *ssh, u_char *typep, u_int32_t *seqnr_p)
193660573Skris{
1937295367Sdes	struct session_state *state = ssh->state;
193899060Sdes	u_int reason, seqnr;
1939295367Sdes	int r;
1940295367Sdes	u_char *msg;
194192555Sdes
194260573Skris	for (;;) {
1943295367Sdes		msg = NULL;
194492555Sdes		if (compat20) {
1945295367Sdes			r = ssh_packet_read_poll2(ssh, typep, seqnr_p);
1946295367Sdes			if (r != 0)
1947295367Sdes				return r;
1948295367Sdes			if (*typep) {
1949295367Sdes				state->keep_alive_timeouts = 0;
1950295367Sdes				DBG(debug("received packet type %d", *typep));
1951181111Sdes			}
1952295367Sdes			switch (*typep) {
195360573Skris			case SSH2_MSG_IGNORE:
1954181111Sdes				debug3("Received SSH2_MSG_IGNORE");
195560573Skris				break;
195660573Skris			case SSH2_MSG_DEBUG:
1957295367Sdes				if ((r = sshpkt_get_u8(ssh, NULL)) != 0 ||
1958295367Sdes				    (r = sshpkt_get_string(ssh, &msg, NULL)) != 0 ||
1959295367Sdes				    (r = sshpkt_get_string(ssh, NULL, NULL)) != 0) {
1960296781Sdes					free(msg);
1961295367Sdes					return r;
1962295367Sdes				}
196360573Skris				debug("Remote: %.900s", msg);
1964255767Sdes				free(msg);
196560573Skris				break;
196660573Skris			case SSH2_MSG_DISCONNECT:
1967295367Sdes				if ((r = sshpkt_get_u32(ssh, &reason)) != 0 ||
1968295367Sdes				    (r = sshpkt_get_string(ssh, &msg, NULL)) != 0)
1969295367Sdes					return r;
1970249475Sdes				/* Ignore normal client exit notifications */
1971295367Sdes				do_log2(ssh->state->server_side &&
1972249475Sdes				    reason == SSH2_DISCONNECT_BY_APPLICATION ?
1973250739Sdes				    SYSLOG_LEVEL_INFO : SYSLOG_LEVEL_ERROR,
1974296781Sdes				    "Received disconnect from %s port %d:"
1975296781Sdes				    "%u: %.400s", ssh_remote_ipaddr(ssh),
1976296781Sdes				    ssh_remote_port(ssh), reason, msg);
1977255767Sdes				free(msg);
1978295367Sdes				return SSH_ERR_DISCONNECTED;
197992555Sdes			case SSH2_MSG_UNIMPLEMENTED:
1980295367Sdes				if ((r = sshpkt_get_u32(ssh, &seqnr)) != 0)
1981295367Sdes					return r;
198299060Sdes				debug("Received SSH2_MSG_UNIMPLEMENTED for %u",
198399060Sdes				    seqnr);
198492555Sdes				break;
198560573Skris			default:
1986295367Sdes				return 0;
198776259Sgreen			}
198860573Skris		} else {
1989295367Sdes			r = ssh_packet_read_poll1(ssh, typep);
1990295367Sdes			switch (*typep) {
1991255767Sdes			case SSH_MSG_NONE:
1992255767Sdes				return SSH_MSG_NONE;
199360573Skris			case SSH_MSG_IGNORE:
199460573Skris				break;
199560573Skris			case SSH_MSG_DEBUG:
1996295367Sdes				if ((r = sshpkt_get_string(ssh, &msg, NULL)) != 0)
1997295367Sdes					return r;
199860573Skris				debug("Remote: %.900s", msg);
1999255767Sdes				free(msg);
200060573Skris				break;
200160573Skris			case SSH_MSG_DISCONNECT:
2002295367Sdes				if ((r = sshpkt_get_string(ssh, &msg, NULL)) != 0)
2003295367Sdes					return r;
2004296781Sdes				logit("Received disconnect from %s port %d: "
2005296781Sdes				    "%.400s", ssh_remote_ipaddr(ssh),
2006296781Sdes				    ssh_remote_port(ssh), msg);
2007295367Sdes				free(msg);
2008295367Sdes				return SSH_ERR_DISCONNECTED;
200960573Skris			default:
2010295367Sdes				DBG(debug("received packet type %d", *typep));
2011295367Sdes				return 0;
201276259Sgreen			}
201360573Skris		}
201460573Skris	}
201560573Skris}
201660573Skris
201757429Smarkm/*
201857429Smarkm * Buffers the given amount of input characters.  This is intended to be used
201957429Smarkm * together with packet_read_poll.
202057429Smarkm */
202157429Smarkm
2022295367Sdesint
2023295367Sdesssh_packet_process_incoming(struct ssh *ssh, const char *buf, u_int len)
202457429Smarkm{
2025295367Sdes	struct session_state *state = ssh->state;
2026295367Sdes	int r;
2027295367Sdes
2028295367Sdes	if (state->packet_discard) {
2029295367Sdes		state->keep_alive_timeouts = 0; /* ?? */
2030295367Sdes		if (len >= state->packet_discard) {
2031295367Sdes			if ((r = ssh_packet_stop_discard(ssh)) != 0)
2032295367Sdes				return r;
2033295367Sdes		}
2034295367Sdes		state->packet_discard -= len;
2035295367Sdes		return 0;
2036192595Sdes	}
2037295367Sdes	if ((r = sshbuf_put(ssh->state->input, buf, len)) != 0)
2038295367Sdes		return r;
203957429Smarkm
2040295367Sdes	return 0;
204157429Smarkm}
204257429Smarkm
204360573Skrisint
2044295367Sdesssh_packet_remaining(struct ssh *ssh)
204560573Skris{
2046295367Sdes	return sshbuf_len(ssh->state->incoming_packet);
204760573Skris}
204860573Skris
204957429Smarkm/*
205057429Smarkm * Sends a diagnostic message from the server to the client.  This message
205157429Smarkm * can be sent at any time (but not while constructing another message). The
205257429Smarkm * message is printed immediately, but only if the client is being executed
205357429Smarkm * in verbose mode.  These messages are primarily intended to ease debugging
205457429Smarkm * authentication problems.   The length of the formatted message must not
2055295367Sdes * exceed 1024 bytes.  This will automatically call ssh_packet_write_wait.
205657429Smarkm */
205757429Smarkmvoid
2058295367Sdesssh_packet_send_debug(struct ssh *ssh, const char *fmt,...)
205957429Smarkm{
206057429Smarkm	char buf[1024];
206157429Smarkm	va_list args;
2062295367Sdes	int r;
206357429Smarkm
2064295367Sdes	if (compat20 && (ssh->compat & SSH_BUG_DEBUG))
206576259Sgreen		return;
206676259Sgreen
206757429Smarkm	va_start(args, fmt);
206857429Smarkm	vsnprintf(buf, sizeof(buf), fmt, args);
206957429Smarkm	va_end(args);
207057429Smarkm
207160573Skris	if (compat20) {
2072295367Sdes		if ((r = sshpkt_start(ssh, SSH2_MSG_DEBUG)) != 0 ||
2073295367Sdes		    (r = sshpkt_put_u8(ssh, 0)) != 0 || /* always display */
2074295367Sdes		    (r = sshpkt_put_cstring(ssh, buf)) != 0 ||
2075295367Sdes		    (r = sshpkt_put_cstring(ssh, "")) != 0 ||
2076295367Sdes		    (r = sshpkt_send(ssh)) != 0)
2077295367Sdes			fatal("%s: %s", __func__, ssh_err(r));
207860573Skris	} else {
2079295367Sdes		if ((r = sshpkt_start(ssh, SSH_MSG_DEBUG)) != 0 ||
2080295367Sdes		    (r = sshpkt_put_cstring(ssh, buf)) != 0 ||
2081295367Sdes		    (r = sshpkt_send(ssh)) != 0)
2082295367Sdes			fatal("%s: %s", __func__, ssh_err(r));
208360573Skris	}
2084295367Sdes	if ((r = ssh_packet_write_wait(ssh)) != 0)
2085295367Sdes		fatal("%s: %s", __func__, ssh_err(r));
208657429Smarkm}
208757429Smarkm
208857429Smarkm/*
2089295367Sdes * Pretty-print connection-terminating errors and exit.
2090295367Sdes */
2091295367Sdesvoid
2092295367Sdessshpkt_fatal(struct ssh *ssh, const char *tag, int r)
2093295367Sdes{
2094295367Sdes	switch (r) {
2095295367Sdes	case SSH_ERR_CONN_CLOSED:
2096323124Sdes		logdie("Connection closed by %.200s port %d",
2097296781Sdes		    ssh_remote_ipaddr(ssh), ssh_remote_port(ssh));
2098295367Sdes	case SSH_ERR_CONN_TIMEOUT:
2099323124Sdes		logdie("Connection %s %.200s port %d timed out",
2100296781Sdes		    ssh->state->server_side ? "from" : "to",
2101296781Sdes		    ssh_remote_ipaddr(ssh), ssh_remote_port(ssh));
2102295367Sdes	case SSH_ERR_DISCONNECTED:
2103323124Sdes		logdie("Disconnected from %.200s port %d",
2104296781Sdes		    ssh_remote_ipaddr(ssh), ssh_remote_port(ssh));
2105295367Sdes	case SSH_ERR_SYSTEM_ERROR:
2106323124Sdes		if (errno == ECONNRESET)
2107323124Sdes			logdie("Connection reset by %.200s port %d",
2108296781Sdes			    ssh_remote_ipaddr(ssh), ssh_remote_port(ssh));
2109295367Sdes		/* FALLTHROUGH */
2110295367Sdes	case SSH_ERR_NO_CIPHER_ALG_MATCH:
2111295367Sdes	case SSH_ERR_NO_MAC_ALG_MATCH:
2112295367Sdes	case SSH_ERR_NO_COMPRESS_ALG_MATCH:
2113295367Sdes	case SSH_ERR_NO_KEX_ALG_MATCH:
2114295367Sdes	case SSH_ERR_NO_HOSTKEY_ALG_MATCH:
2115295367Sdes		if (ssh && ssh->kex && ssh->kex->failed_choice) {
2116323124Sdes			logdie("Unable to negotiate with %.200s port %d: %s. "
2117295367Sdes			    "Their offer: %s", ssh_remote_ipaddr(ssh),
2118296781Sdes			    ssh_remote_port(ssh), ssh_err(r),
2119296781Sdes			    ssh->kex->failed_choice);
2120295367Sdes		}
2121295367Sdes		/* FALLTHROUGH */
2122295367Sdes	default:
2123323124Sdes		logdie("%s%sConnection %s %.200s port %d: %s",
2124295367Sdes		    tag != NULL ? tag : "", tag != NULL ? ": " : "",
2125296781Sdes		    ssh->state->server_side ? "from" : "to",
2126296781Sdes		    ssh_remote_ipaddr(ssh), ssh_remote_port(ssh), ssh_err(r));
2127295367Sdes	}
2128295367Sdes}
2129295367Sdes
2130295367Sdes/*
213157429Smarkm * Logs the error plus constructs and sends a disconnect packet, closes the
213257429Smarkm * connection, and exits.  This function never returns. The error message
213357429Smarkm * should not contain a newline.  The length of the formatted message must
213457429Smarkm * not exceed 1024 bytes.
213557429Smarkm */
213657429Smarkmvoid
2137295367Sdesssh_packet_disconnect(struct ssh *ssh, const char *fmt,...)
213857429Smarkm{
213957429Smarkm	char buf[1024];
214057429Smarkm	va_list args;
214157429Smarkm	static int disconnecting = 0;
2142295367Sdes	int r;
2143106121Sdes
214457429Smarkm	if (disconnecting)	/* Guard against recursive invocations. */
214557429Smarkm		fatal("packet_disconnect called recursively.");
214657429Smarkm	disconnecting = 1;
214757429Smarkm
214857429Smarkm	/*
214957429Smarkm	 * Format the message.  Note that the caller must make sure the
215057429Smarkm	 * message is of limited size.
215157429Smarkm	 */
215257429Smarkm	va_start(args, fmt);
215357429Smarkm	vsnprintf(buf, sizeof(buf), fmt, args);
215457429Smarkm	va_end(args);
215557429Smarkm
2156113908Sdes	/* Display the error locally */
2157124208Sdes	logit("Disconnecting: %.100s", buf);
2158113908Sdes
2159295367Sdes	/*
2160295367Sdes	 * Send the disconnect message to the other side, and wait
2161295367Sdes	 * for it to get sent.
2162295367Sdes	 */
2163295367Sdes	if ((r = sshpkt_disconnect(ssh, "%s", buf)) != 0)
2164295367Sdes		sshpkt_fatal(ssh, __func__, r);
216557429Smarkm
2166295367Sdes	if ((r = ssh_packet_write_wait(ssh)) != 0)
2167295367Sdes		sshpkt_fatal(ssh, __func__, r);
216857429Smarkm
216957429Smarkm	/* Close the connection. */
2170295367Sdes	ssh_packet_close(ssh);
2171126274Sdes	cleanup_exit(255);
217257429Smarkm}
217357429Smarkm
2174295367Sdes/*
2175295367Sdes * Checks if there is any buffered output, and tries to write some of
2176295367Sdes * the output.
2177295367Sdes */
2178295367Sdesint
2179295367Sdesssh_packet_write_poll(struct ssh *ssh)
218057429Smarkm{
2181295367Sdes	struct session_state *state = ssh->state;
2182295367Sdes	int len = sshbuf_len(state->output);
2183296781Sdes	int r;
2184106121Sdes
218557429Smarkm	if (len > 0) {
2186296781Sdes		len = write(state->connection_out,
2187296781Sdes		    sshbuf_ptr(state->output), len);
2188181111Sdes		if (len == -1) {
2189181111Sdes			if (errno == EINTR || errno == EAGAIN ||
2190181111Sdes			    errno == EWOULDBLOCK)
2191295367Sdes				return 0;
2192295367Sdes			return SSH_ERR_SYSTEM_ERROR;
219357429Smarkm		}
2194296781Sdes		if (len == 0)
2195295367Sdes			return SSH_ERR_CONN_CLOSED;
2196295367Sdes		if ((r = sshbuf_consume(state->output, len)) != 0)
2197295367Sdes			return r;
219857429Smarkm	}
2199295367Sdes	return 0;
220057429Smarkm}
220157429Smarkm
220257429Smarkm/*
220357429Smarkm * Calls packet_write_poll repeatedly until all pending output data has been
220457429Smarkm * written.
220557429Smarkm */
2206295367Sdesint
2207295367Sdesssh_packet_write_wait(struct ssh *ssh)
220857429Smarkm{
220976259Sgreen	fd_set *setp;
2210295367Sdes	int ret, r, ms_remain = 0;
2211181111Sdes	struct timeval start, timeout, *timeoutp = NULL;
2212295367Sdes	struct session_state *state = ssh->state;
221376259Sgreen
2214295367Sdes	setp = calloc(howmany(state->connection_out + 1,
2215197679Sdes	    NFDBITS), sizeof(fd_mask));
2216295367Sdes	if (setp == NULL)
2217295367Sdes		return SSH_ERR_ALLOC_FAIL;
2218296781Sdes	if ((r = ssh_packet_write_poll(ssh)) != 0) {
2219296781Sdes		free(setp);
2220296781Sdes		return r;
2221296781Sdes	}
2222295367Sdes	while (ssh_packet_have_data_to_write(ssh)) {
2223295367Sdes		memset(setp, 0, howmany(state->connection_out + 1,
2224197679Sdes		    NFDBITS) * sizeof(fd_mask));
2225295367Sdes		FD_SET(state->connection_out, setp);
2226181111Sdes
2227295367Sdes		if (state->packet_timeout_ms > 0) {
2228295367Sdes			ms_remain = state->packet_timeout_ms;
2229181111Sdes			timeoutp = &timeout;
2230181111Sdes		}
2231181111Sdes		for (;;) {
2232295367Sdes			if (state->packet_timeout_ms != -1) {
2233181111Sdes				ms_to_timeval(&timeout, ms_remain);
2234181111Sdes				gettimeofday(&start, NULL);
2235181111Sdes			}
2236295367Sdes			if ((ret = select(state->connection_out + 1,
2237197679Sdes			    NULL, setp, NULL, timeoutp)) >= 0)
2238181111Sdes				break;
2239197679Sdes			if (errno != EAGAIN && errno != EINTR &&
2240181111Sdes			    errno != EWOULDBLOCK)
2241181111Sdes				break;
2242295367Sdes			if (state->packet_timeout_ms == -1)
2243181111Sdes				continue;
2244181111Sdes			ms_subtract_diff(&start, &ms_remain);
2245181111Sdes			if (ms_remain <= 0) {
2246181111Sdes				ret = 0;
2247181111Sdes				break;
2248181111Sdes			}
2249181111Sdes		}
2250181111Sdes		if (ret == 0) {
2251295367Sdes			free(setp);
2252295367Sdes			return SSH_ERR_CONN_TIMEOUT;
2253181111Sdes		}
2254295367Sdes		if ((r = ssh_packet_write_poll(ssh)) != 0) {
2255295367Sdes			free(setp);
2256295367Sdes			return r;
2257295367Sdes		}
225857429Smarkm	}
2259255767Sdes	free(setp);
2260295367Sdes	return 0;
226157429Smarkm}
226257429Smarkm
226357429Smarkm/* Returns true if there is buffered data to write to the connection. */
226457429Smarkm
226557429Smarkmint
2266295367Sdesssh_packet_have_data_to_write(struct ssh *ssh)
226757429Smarkm{
2268295367Sdes	return sshbuf_len(ssh->state->output) != 0;
226957429Smarkm}
227057429Smarkm
227157429Smarkm/* Returns true if there is not too much data to write to the connection. */
227257429Smarkm
227357429Smarkmint
2274295367Sdesssh_packet_not_very_much_data_to_write(struct ssh *ssh)
227557429Smarkm{
2276295367Sdes	if (ssh->state->interactive_mode)
2277295367Sdes		return sshbuf_len(ssh->state->output) < 16384;
227857429Smarkm	else
2279295367Sdes		return sshbuf_len(ssh->state->output) < 128 * 1024;
228057429Smarkm}
228157429Smarkm
2282295367Sdesvoid
2283295367Sdesssh_packet_set_tos(struct ssh *ssh, int tos)
2284113908Sdes{
2285226046Sdes#ifndef IP_TOS_IS_BROKEN
2286295367Sdes	if (!ssh_packet_connection_is_on_socket(ssh))
2287113908Sdes		return;
2288295367Sdes	switch (ssh_packet_connection_af(ssh)) {
2289226046Sdes# ifdef IP_TOS
2290226046Sdes	case AF_INET:
2291226046Sdes		debug3("%s: set IP_TOS 0x%02x", __func__, tos);
2292295367Sdes		if (setsockopt(ssh->state->connection_in,
2293226046Sdes		    IPPROTO_IP, IP_TOS, &tos, sizeof(tos)) < 0)
2294226046Sdes			error("setsockopt IP_TOS %d: %.100s:",
2295226046Sdes			    tos, strerror(errno));
2296226046Sdes		break;
2297226046Sdes# endif /* IP_TOS */
2298226046Sdes# ifdef IPV6_TCLASS
2299226046Sdes	case AF_INET6:
2300226046Sdes		debug3("%s: set IPV6_TCLASS 0x%02x", __func__, tos);
2301295367Sdes		if (setsockopt(ssh->state->connection_in,
2302226046Sdes		    IPPROTO_IPV6, IPV6_TCLASS, &tos, sizeof(tos)) < 0)
2303226046Sdes			error("setsockopt IPV6_TCLASS %d: %.100s:",
2304226046Sdes			    tos, strerror(errno));
2305226046Sdes		break;
2306226046Sdes# endif /* IPV6_TCLASS */
2307226046Sdes	}
2308226046Sdes#endif /* IP_TOS_IS_BROKEN */
2309113908Sdes}
2310113908Sdes
231157429Smarkm/* Informs that the current session is interactive.  Sets IP flags for that. */
231257429Smarkm
231357429Smarkmvoid
2314295367Sdesssh_packet_set_interactive(struct ssh *ssh, int interactive, int qos_interactive, int qos_bulk)
231557429Smarkm{
2316295367Sdes	struct session_state *state = ssh->state;
2317295367Sdes
2318295367Sdes	if (state->set_interactive_called)
231976259Sgreen		return;
2320295367Sdes	state->set_interactive_called = 1;
232176259Sgreen
232257429Smarkm	/* Record that we are in interactive mode. */
2323295367Sdes	state->interactive_mode = interactive;
232457429Smarkm
232557429Smarkm	/* Only set socket options if using a socket.  */
2326295367Sdes	if (!ssh_packet_connection_is_on_socket(ssh))
2327116791Sdes		return;
2328295367Sdes	set_nodelay(state->connection_in);
2329295367Sdes	ssh_packet_set_tos(ssh, interactive ? qos_interactive :
2330295367Sdes	    qos_bulk);
233157429Smarkm}
233257429Smarkm
233357429Smarkm/* Returns true if the current connection is interactive. */
233457429Smarkm
233557429Smarkmint
2336295367Sdesssh_packet_is_interactive(struct ssh *ssh)
233757429Smarkm{
2338295367Sdes	return ssh->state->interactive_mode;
233957429Smarkm}
234057429Smarkm
2341137015Sdesint
2342295367Sdesssh_packet_set_maxsize(struct ssh *ssh, u_int s)
234357429Smarkm{
2344295367Sdes	struct session_state *state = ssh->state;
2345295367Sdes
2346295367Sdes	if (state->set_maxsize_called) {
2347124208Sdes		logit("packet_set_maxsize: called twice: old %d new %d",
2348295367Sdes		    state->max_packet_size, s);
234957429Smarkm		return -1;
235057429Smarkm	}
235157429Smarkm	if (s < 4 * 1024 || s > 1024 * 1024) {
2352124208Sdes		logit("packet_set_maxsize: bad size %d", s);
235357429Smarkm		return -1;
235457429Smarkm	}
2355295367Sdes	state->set_maxsize_called = 1;
235692555Sdes	debug("packet_set_maxsize: setting to %d", s);
2357295367Sdes	state->max_packet_size = s;
235857429Smarkm	return s;
235957429Smarkm}
236076259Sgreen
2361197679Sdesint
2362295367Sdesssh_packet_inc_alive_timeouts(struct ssh *ssh)
2363197679Sdes{
2364295367Sdes	return ++ssh->state->keep_alive_timeouts;
2365197679Sdes}
2366197679Sdes
2367197679Sdesvoid
2368295367Sdesssh_packet_set_alive_timeouts(struct ssh *ssh, int ka)
2369197679Sdes{
2370295367Sdes	ssh->state->keep_alive_timeouts = ka;
2371197679Sdes}
2372197679Sdes
2373197679Sdesu_int
2374295367Sdesssh_packet_get_maxsize(struct ssh *ssh)
2375197679Sdes{
2376295367Sdes	return ssh->state->max_packet_size;
2377197679Sdes}
2378197679Sdes
237976259Sgreen/*
238076259Sgreen * 9.2.  Ignored Data Message
238176259Sgreen *
238276259Sgreen *   byte      SSH_MSG_IGNORE
238376259Sgreen *   string    data
238476259Sgreen *
238576259Sgreen * All implementations MUST understand (and ignore) this message at any
238676259Sgreen * time (after receiving the protocol version). No implementation is
238776259Sgreen * required to send them. This message can be used as an additional
238876259Sgreen * protection measure against advanced traffic analysis techniques.
238976259Sgreen */
239076259Sgreenvoid
2391295367Sdesssh_packet_send_ignore(struct ssh *ssh, int nbytes)
239276259Sgreen{
2393137015Sdes	u_int32_t rnd = 0;
2394295367Sdes	int r, i;
239576259Sgreen
2396295367Sdes	if ((r = sshpkt_start(ssh, compat20 ?
2397295367Sdes	    SSH2_MSG_IGNORE : SSH_MSG_IGNORE)) != 0 ||
2398295367Sdes	    (r = sshpkt_put_u32(ssh, nbytes)) != 0)
2399295367Sdes		fatal("%s: %s", __func__, ssh_err(r));
240092555Sdes	for (i = 0; i < nbytes; i++) {
240176259Sgreen		if (i % 4 == 0)
2402137015Sdes			rnd = arc4random();
2403295367Sdes		if ((r = sshpkt_put_u8(ssh, (u_char)rnd & 0xff)) != 0)
2404295367Sdes			fatal("%s: %s", __func__, ssh_err(r));
2405137015Sdes		rnd >>= 8;
240676259Sgreen	}
240776259Sgreen}
2408124208Sdes
2409124208Sdesvoid
2410296781Sdesssh_packet_set_rekey_limits(struct ssh *ssh, u_int64_t bytes, time_t seconds)
2411124208Sdes{
2412296781Sdes	debug3("rekey after %llu bytes, %d seconds", (unsigned long long)bytes,
2413255767Sdes	    (int)seconds);
2414295367Sdes	ssh->state->rekey_limit = bytes;
2415295367Sdes	ssh->state->rekey_interval = seconds;
2416124208Sdes}
2417149749Sdes
2418255767Sdestime_t
2419295367Sdesssh_packet_get_rekey_timeout(struct ssh *ssh)
2420255767Sdes{
2421255767Sdes	time_t seconds;
2422255767Sdes
2423295367Sdes	seconds = ssh->state->rekey_time + ssh->state->rekey_interval -
2424255767Sdes	    monotime();
2425255767Sdes	return (seconds <= 0 ? 1 : seconds);
2426255767Sdes}
2427255767Sdes
2428149749Sdesvoid
2429295367Sdesssh_packet_set_server(struct ssh *ssh)
2430149749Sdes{
2431295367Sdes	ssh->state->server_side = 1;
2432149749Sdes}
2433149749Sdes
2434149749Sdesvoid
2435295367Sdesssh_packet_set_authenticated(struct ssh *ssh)
2436149749Sdes{
2437295367Sdes	ssh->state->after_authentication = 1;
2438149749Sdes}
2439197679Sdes
2440197679Sdesvoid *
2441295367Sdesssh_packet_get_input(struct ssh *ssh)
2442197679Sdes{
2443295367Sdes	return (void *)ssh->state->input;
2444197679Sdes}
2445197679Sdes
2446197679Sdesvoid *
2447295367Sdesssh_packet_get_output(struct ssh *ssh)
2448197679Sdes{
2449295367Sdes	return (void *)ssh->state->output;
2450197679Sdes}
2451197679Sdes
2452295367Sdes/* Reset after_authentication and reset compression in post-auth privsep */
2453295367Sdesstatic int
2454295367Sdesssh_packet_set_postauth(struct ssh *ssh)
2455295367Sdes{
2456295367Sdes	struct sshcomp *comp;
2457295367Sdes	int r, mode;
2458295367Sdes
2459295367Sdes	debug("%s: called", __func__);
2460295367Sdes	/* This was set in net child, but is not visible in user child */
2461295367Sdes	ssh->state->after_authentication = 1;
2462295367Sdes	ssh->state->rekeying = 0;
2463295367Sdes	for (mode = 0; mode < MODE_MAX; mode++) {
2464295367Sdes		if (ssh->state->newkeys[mode] == NULL)
2465295367Sdes			continue;
2466295367Sdes		comp = &ssh->state->newkeys[mode]->comp;
2467295367Sdes		if (comp && comp->enabled &&
2468295367Sdes		    (r = ssh_packet_init_compression(ssh)) != 0)
2469295367Sdes			return r;
2470295367Sdes	}
2471295367Sdes	return 0;
2472295367Sdes}
2473295367Sdes
2474295367Sdes/* Packet state (de-)serialization for privsep */
2475295367Sdes
2476295367Sdes/* turn kex into a blob for packet state serialization */
2477295367Sdesstatic int
2478295367Sdeskex_to_blob(struct sshbuf *m, struct kex *kex)
2479295367Sdes{
2480295367Sdes	int r;
2481295367Sdes
2482295367Sdes	if ((r = sshbuf_put_string(m, kex->session_id,
2483295367Sdes	    kex->session_id_len)) != 0 ||
2484295367Sdes	    (r = sshbuf_put_u32(m, kex->we_need)) != 0 ||
2485295367Sdes	    (r = sshbuf_put_u32(m, kex->hostkey_type)) != 0 ||
2486295367Sdes	    (r = sshbuf_put_u32(m, kex->kex_type)) != 0 ||
2487295367Sdes	    (r = sshbuf_put_stringb(m, kex->my)) != 0 ||
2488295367Sdes	    (r = sshbuf_put_stringb(m, kex->peer)) != 0 ||
2489295367Sdes	    (r = sshbuf_put_u32(m, kex->flags)) != 0 ||
2490295367Sdes	    (r = sshbuf_put_cstring(m, kex->client_version_string)) != 0 ||
2491295367Sdes	    (r = sshbuf_put_cstring(m, kex->server_version_string)) != 0)
2492295367Sdes		return r;
2493295367Sdes	return 0;
2494295367Sdes}
2495295367Sdes
2496295367Sdes/* turn key exchange results into a blob for packet state serialization */
2497295367Sdesstatic int
2498295367Sdesnewkeys_to_blob(struct sshbuf *m, struct ssh *ssh, int mode)
2499295367Sdes{
2500295367Sdes	struct sshbuf *b;
2501295367Sdes	struct sshcipher_ctx *cc;
2502295367Sdes	struct sshcomp *comp;
2503295367Sdes	struct sshenc *enc;
2504295367Sdes	struct sshmac *mac;
2505295367Sdes	struct newkeys *newkey;
2506295367Sdes	int r;
2507295367Sdes
2508295367Sdes	if ((newkey = ssh->state->newkeys[mode]) == NULL)
2509295367Sdes		return SSH_ERR_INTERNAL_ERROR;
2510295367Sdes	enc = &newkey->enc;
2511295367Sdes	mac = &newkey->mac;
2512295367Sdes	comp = &newkey->comp;
2513295367Sdes	cc = (mode == MODE_OUT) ? &ssh->state->send_context :
2514295367Sdes	    &ssh->state->receive_context;
2515295367Sdes	if ((r = cipher_get_keyiv(cc, enc->iv, enc->iv_len)) != 0)
2516295367Sdes		return r;
2517295367Sdes	if ((b = sshbuf_new()) == NULL)
2518295367Sdes		return SSH_ERR_ALLOC_FAIL;
2519295367Sdes	/* The cipher struct is constant and shared, you export pointer */
2520295367Sdes	if ((r = sshbuf_put_cstring(b, enc->name)) != 0 ||
2521295367Sdes	    (r = sshbuf_put(b, &enc->cipher, sizeof(enc->cipher))) != 0 ||
2522295367Sdes	    (r = sshbuf_put_u32(b, enc->enabled)) != 0 ||
2523295367Sdes	    (r = sshbuf_put_u32(b, enc->block_size)) != 0 ||
2524295367Sdes	    (r = sshbuf_put_string(b, enc->key, enc->key_len)) != 0 ||
2525295367Sdes	    (r = sshbuf_put_string(b, enc->iv, enc->iv_len)) != 0)
2526295367Sdes		goto out;
2527295367Sdes	if (cipher_authlen(enc->cipher) == 0) {
2528295367Sdes		if ((r = sshbuf_put_cstring(b, mac->name)) != 0 ||
2529295367Sdes		    (r = sshbuf_put_u32(b, mac->enabled)) != 0 ||
2530295367Sdes		    (r = sshbuf_put_string(b, mac->key, mac->key_len)) != 0)
2531295367Sdes			goto out;
2532295367Sdes	}
2533295367Sdes	if ((r = sshbuf_put_u32(b, comp->type)) != 0 ||
2534295367Sdes	    (r = sshbuf_put_u32(b, comp->enabled)) != 0 ||
2535295367Sdes	    (r = sshbuf_put_cstring(b, comp->name)) != 0)
2536295367Sdes		goto out;
2537295367Sdes	r = sshbuf_put_stringb(m, b);
2538295367Sdes out:
2539296781Sdes	sshbuf_free(b);
2540295367Sdes	return r;
2541295367Sdes}
2542295367Sdes
2543295367Sdes/* serialize packet state into a blob */
2544295367Sdesint
2545295367Sdesssh_packet_get_state(struct ssh *ssh, struct sshbuf *m)
2546295367Sdes{
2547295367Sdes	struct session_state *state = ssh->state;
2548295367Sdes	u_char *p;
2549295367Sdes	size_t slen, rlen;
2550295367Sdes	int r, ssh1cipher;
2551295367Sdes
2552295367Sdes	if (!compat20) {
2553295367Sdes		ssh1cipher = cipher_get_number(state->receive_context.cipher);
2554295367Sdes		slen = cipher_get_keyiv_len(&state->send_context);
2555295367Sdes		rlen = cipher_get_keyiv_len(&state->receive_context);
2556295367Sdes		if ((r = sshbuf_put_u32(m, state->remote_protocol_flags)) != 0 ||
2557295367Sdes		    (r = sshbuf_put_u32(m, ssh1cipher)) != 0 ||
2558295367Sdes		    (r = sshbuf_put_string(m, state->ssh1_key, state->ssh1_keylen)) != 0 ||
2559295367Sdes		    (r = sshbuf_put_u32(m, slen)) != 0 ||
2560295367Sdes		    (r = sshbuf_reserve(m, slen, &p)) != 0 ||
2561295367Sdes		    (r = cipher_get_keyiv(&state->send_context, p, slen)) != 0 ||
2562295367Sdes		    (r = sshbuf_put_u32(m, rlen)) != 0 ||
2563295367Sdes		    (r = sshbuf_reserve(m, rlen, &p)) != 0 ||
2564295367Sdes		    (r = cipher_get_keyiv(&state->receive_context, p, rlen)) != 0)
2565295367Sdes			return r;
2566295367Sdes	} else {
2567295367Sdes		if ((r = kex_to_blob(m, ssh->kex)) != 0 ||
2568295367Sdes		    (r = newkeys_to_blob(m, ssh, MODE_OUT)) != 0 ||
2569295367Sdes		    (r = newkeys_to_blob(m, ssh, MODE_IN)) != 0 ||
2570296781Sdes		    (r = sshbuf_put_u64(m, state->rekey_limit)) != 0 ||
2571295367Sdes		    (r = sshbuf_put_u32(m, state->rekey_interval)) != 0 ||
2572295367Sdes		    (r = sshbuf_put_u32(m, state->p_send.seqnr)) != 0 ||
2573295367Sdes		    (r = sshbuf_put_u64(m, state->p_send.blocks)) != 0 ||
2574295367Sdes		    (r = sshbuf_put_u32(m, state->p_send.packets)) != 0 ||
2575295367Sdes		    (r = sshbuf_put_u64(m, state->p_send.bytes)) != 0 ||
2576295367Sdes		    (r = sshbuf_put_u32(m, state->p_read.seqnr)) != 0 ||
2577295367Sdes		    (r = sshbuf_put_u64(m, state->p_read.blocks)) != 0 ||
2578295367Sdes		    (r = sshbuf_put_u32(m, state->p_read.packets)) != 0 ||
2579295367Sdes		    (r = sshbuf_put_u64(m, state->p_read.bytes)) != 0)
2580295367Sdes			return r;
2581295367Sdes	}
2582295367Sdes
2583295367Sdes	slen = cipher_get_keycontext(&state->send_context, NULL);
2584295367Sdes	rlen = cipher_get_keycontext(&state->receive_context, NULL);
2585295367Sdes	if ((r = sshbuf_put_u32(m, slen)) != 0 ||
2586295367Sdes	    (r = sshbuf_reserve(m, slen, &p)) != 0)
2587295367Sdes		return r;
2588295367Sdes	if (cipher_get_keycontext(&state->send_context, p) != (int)slen)
2589295367Sdes		return SSH_ERR_INTERNAL_ERROR;
2590295367Sdes	if ((r = sshbuf_put_u32(m, rlen)) != 0 ||
2591295367Sdes	    (r = sshbuf_reserve(m, rlen, &p)) != 0)
2592295367Sdes		return r;
2593295367Sdes	if (cipher_get_keycontext(&state->receive_context, p) != (int)rlen)
2594295367Sdes		return SSH_ERR_INTERNAL_ERROR;
2595295367Sdes
2596295367Sdes	if ((r = ssh_packet_get_compress_state(m, ssh)) != 0 ||
2597295367Sdes	    (r = sshbuf_put_stringb(m, state->input)) != 0 ||
2598295367Sdes	    (r = sshbuf_put_stringb(m, state->output)) != 0)
2599295367Sdes		return r;
2600295367Sdes
2601295367Sdes	return 0;
2602295367Sdes}
2603295367Sdes
2604295367Sdes/* restore key exchange results from blob for packet state de-serialization */
2605295367Sdesstatic int
2606295367Sdesnewkeys_from_blob(struct sshbuf *m, struct ssh *ssh, int mode)
2607295367Sdes{
2608295367Sdes	struct sshbuf *b = NULL;
2609295367Sdes	struct sshcomp *comp;
2610295367Sdes	struct sshenc *enc;
2611295367Sdes	struct sshmac *mac;
2612295367Sdes	struct newkeys *newkey = NULL;
2613295367Sdes	size_t keylen, ivlen, maclen;
2614295367Sdes	int r;
2615295367Sdes
2616295367Sdes	if ((newkey = calloc(1, sizeof(*newkey))) == NULL) {
2617295367Sdes		r = SSH_ERR_ALLOC_FAIL;
2618295367Sdes		goto out;
2619295367Sdes	}
2620295367Sdes	if ((r = sshbuf_froms(m, &b)) != 0)
2621295367Sdes		goto out;
2622295367Sdes#ifdef DEBUG_PK
2623295367Sdes	sshbuf_dump(b, stderr);
2624295367Sdes#endif
2625295367Sdes	enc = &newkey->enc;
2626295367Sdes	mac = &newkey->mac;
2627295367Sdes	comp = &newkey->comp;
2628295367Sdes
2629295367Sdes	if ((r = sshbuf_get_cstring(b, &enc->name, NULL)) != 0 ||
2630295367Sdes	    (r = sshbuf_get(b, &enc->cipher, sizeof(enc->cipher))) != 0 ||
2631295367Sdes	    (r = sshbuf_get_u32(b, (u_int *)&enc->enabled)) != 0 ||
2632295367Sdes	    (r = sshbuf_get_u32(b, &enc->block_size)) != 0 ||
2633295367Sdes	    (r = sshbuf_get_string(b, &enc->key, &keylen)) != 0 ||
2634295367Sdes	    (r = sshbuf_get_string(b, &enc->iv, &ivlen)) != 0)
2635295367Sdes		goto out;
2636295367Sdes	if (cipher_authlen(enc->cipher) == 0) {
2637295367Sdes		if ((r = sshbuf_get_cstring(b, &mac->name, NULL)) != 0)
2638295367Sdes			goto out;
2639295367Sdes		if ((r = mac_setup(mac, mac->name)) != 0)
2640295367Sdes			goto out;
2641295367Sdes		if ((r = sshbuf_get_u32(b, (u_int *)&mac->enabled)) != 0 ||
2642295367Sdes		    (r = sshbuf_get_string(b, &mac->key, &maclen)) != 0)
2643295367Sdes			goto out;
2644295367Sdes		if (maclen > mac->key_len) {
2645295367Sdes			r = SSH_ERR_INVALID_FORMAT;
2646295367Sdes			goto out;
2647295367Sdes		}
2648295367Sdes		mac->key_len = maclen;
2649295367Sdes	}
2650295367Sdes	if ((r = sshbuf_get_u32(b, &comp->type)) != 0 ||
2651295367Sdes	    (r = sshbuf_get_u32(b, (u_int *)&comp->enabled)) != 0 ||
2652295367Sdes	    (r = sshbuf_get_cstring(b, &comp->name, NULL)) != 0)
2653295367Sdes		goto out;
2654295367Sdes	if (enc->name == NULL ||
2655295367Sdes	    cipher_by_name(enc->name) != enc->cipher) {
2656295367Sdes		r = SSH_ERR_INVALID_FORMAT;
2657295367Sdes		goto out;
2658295367Sdes	}
2659295367Sdes	if (sshbuf_len(b) != 0) {
2660295367Sdes		r = SSH_ERR_INVALID_FORMAT;
2661295367Sdes		goto out;
2662295367Sdes	}
2663295367Sdes	enc->key_len = keylen;
2664295367Sdes	enc->iv_len = ivlen;
2665295367Sdes	ssh->kex->newkeys[mode] = newkey;
2666295367Sdes	newkey = NULL;
2667295367Sdes	r = 0;
2668295367Sdes out:
2669296781Sdes	free(newkey);
2670296781Sdes	sshbuf_free(b);
2671295367Sdes	return r;
2672295367Sdes}
2673295367Sdes
2674295367Sdes/* restore kex from blob for packet state de-serialization */
2675295367Sdesstatic int
2676295367Sdeskex_from_blob(struct sshbuf *m, struct kex **kexp)
2677295367Sdes{
2678295367Sdes	struct kex *kex;
2679295367Sdes	int r;
2680295367Sdes
2681295367Sdes	if ((kex = calloc(1, sizeof(struct kex))) == NULL ||
2682295367Sdes	    (kex->my = sshbuf_new()) == NULL ||
2683295367Sdes	    (kex->peer = sshbuf_new()) == NULL) {
2684295367Sdes		r = SSH_ERR_ALLOC_FAIL;
2685295367Sdes		goto out;
2686295367Sdes	}
2687295367Sdes	if ((r = sshbuf_get_string(m, &kex->session_id, &kex->session_id_len)) != 0 ||
2688295367Sdes	    (r = sshbuf_get_u32(m, &kex->we_need)) != 0 ||
2689295367Sdes	    (r = sshbuf_get_u32(m, (u_int *)&kex->hostkey_type)) != 0 ||
2690295367Sdes	    (r = sshbuf_get_u32(m, &kex->kex_type)) != 0 ||
2691295367Sdes	    (r = sshbuf_get_stringb(m, kex->my)) != 0 ||
2692295367Sdes	    (r = sshbuf_get_stringb(m, kex->peer)) != 0 ||
2693295367Sdes	    (r = sshbuf_get_u32(m, &kex->flags)) != 0 ||
2694295367Sdes	    (r = sshbuf_get_cstring(m, &kex->client_version_string, NULL)) != 0 ||
2695295367Sdes	    (r = sshbuf_get_cstring(m, &kex->server_version_string, NULL)) != 0)
2696295367Sdes		goto out;
2697295367Sdes	kex->server = 1;
2698295367Sdes	kex->done = 1;
2699295367Sdes	r = 0;
2700295367Sdes out:
2701295367Sdes	if (r != 0 || kexp == NULL) {
2702295367Sdes		if (kex != NULL) {
2703296781Sdes			sshbuf_free(kex->my);
2704296781Sdes			sshbuf_free(kex->peer);
2705295367Sdes			free(kex);
2706295367Sdes		}
2707295367Sdes		if (kexp != NULL)
2708295367Sdes			*kexp = NULL;
2709295367Sdes	} else {
2710295367Sdes		*kexp = kex;
2711295367Sdes	}
2712295367Sdes	return r;
2713295367Sdes}
2714295367Sdes
2715295367Sdes/*
2716295367Sdes * Restore packet state from content of blob 'm' (de-serialization).
2717295367Sdes * Note that 'm' will be partially consumed on parsing or any other errors.
2718295367Sdes */
2719295367Sdesint
2720295367Sdesssh_packet_set_state(struct ssh *ssh, struct sshbuf *m)
2721295367Sdes{
2722295367Sdes	struct session_state *state = ssh->state;
2723295367Sdes	const u_char *ssh1key, *ivin, *ivout, *keyin, *keyout, *input, *output;
2724295367Sdes	size_t ssh1keylen, rlen, slen, ilen, olen;
2725295367Sdes	int r;
2726295367Sdes	u_int ssh1cipher = 0;
2727295367Sdes
2728295367Sdes	if (!compat20) {
2729295367Sdes		if ((r = sshbuf_get_u32(m, &state->remote_protocol_flags)) != 0 ||
2730295367Sdes		    (r = sshbuf_get_u32(m, &ssh1cipher)) != 0 ||
2731295367Sdes		    (r = sshbuf_get_string_direct(m, &ssh1key, &ssh1keylen)) != 0 ||
2732295367Sdes		    (r = sshbuf_get_string_direct(m, &ivout, &slen)) != 0 ||
2733295367Sdes		    (r = sshbuf_get_string_direct(m, &ivin, &rlen)) != 0)
2734295367Sdes			return r;
2735295367Sdes		if (ssh1cipher > INT_MAX)
2736295367Sdes			return SSH_ERR_KEY_UNKNOWN_CIPHER;
2737295367Sdes		ssh_packet_set_encryption_key(ssh, ssh1key, ssh1keylen,
2738295367Sdes		    (int)ssh1cipher);
2739295367Sdes		if (cipher_get_keyiv_len(&state->send_context) != (int)slen ||
2740295367Sdes		    cipher_get_keyiv_len(&state->receive_context) != (int)rlen)
2741295367Sdes			return SSH_ERR_INVALID_FORMAT;
2742295367Sdes		if ((r = cipher_set_keyiv(&state->send_context, ivout)) != 0 ||
2743295367Sdes		    (r = cipher_set_keyiv(&state->receive_context, ivin)) != 0)
2744295367Sdes			return r;
2745295367Sdes	} else {
2746295367Sdes		if ((r = kex_from_blob(m, &ssh->kex)) != 0 ||
2747295367Sdes		    (r = newkeys_from_blob(m, ssh, MODE_OUT)) != 0 ||
2748295367Sdes		    (r = newkeys_from_blob(m, ssh, MODE_IN)) != 0 ||
2749296781Sdes		    (r = sshbuf_get_u64(m, &state->rekey_limit)) != 0 ||
2750295367Sdes		    (r = sshbuf_get_u32(m, &state->rekey_interval)) != 0 ||
2751295367Sdes		    (r = sshbuf_get_u32(m, &state->p_send.seqnr)) != 0 ||
2752295367Sdes		    (r = sshbuf_get_u64(m, &state->p_send.blocks)) != 0 ||
2753295367Sdes		    (r = sshbuf_get_u32(m, &state->p_send.packets)) != 0 ||
2754295367Sdes		    (r = sshbuf_get_u64(m, &state->p_send.bytes)) != 0 ||
2755295367Sdes		    (r = sshbuf_get_u32(m, &state->p_read.seqnr)) != 0 ||
2756295367Sdes		    (r = sshbuf_get_u64(m, &state->p_read.blocks)) != 0 ||
2757295367Sdes		    (r = sshbuf_get_u32(m, &state->p_read.packets)) != 0 ||
2758295367Sdes		    (r = sshbuf_get_u64(m, &state->p_read.bytes)) != 0)
2759295367Sdes			return r;
2760295367Sdes		/*
2761295367Sdes		 * We set the time here so that in post-auth privsep slave we
2762295367Sdes		 * count from the completion of the authentication.
2763295367Sdes		 */
2764295367Sdes		state->rekey_time = monotime();
2765295367Sdes		/* XXX ssh_set_newkeys overrides p_read.packets? XXX */
2766295367Sdes		if ((r = ssh_set_newkeys(ssh, MODE_IN)) != 0 ||
2767295367Sdes		    (r = ssh_set_newkeys(ssh, MODE_OUT)) != 0)
2768295367Sdes			return r;
2769295367Sdes	}
2770295367Sdes	if ((r = sshbuf_get_string_direct(m, &keyout, &slen)) != 0 ||
2771295367Sdes	    (r = sshbuf_get_string_direct(m, &keyin, &rlen)) != 0)
2772295367Sdes		return r;
2773295367Sdes	if (cipher_get_keycontext(&state->send_context, NULL) != (int)slen ||
2774295367Sdes	    cipher_get_keycontext(&state->receive_context, NULL) != (int)rlen)
2775295367Sdes		return SSH_ERR_INVALID_FORMAT;
2776295367Sdes	cipher_set_keycontext(&state->send_context, keyout);
2777295367Sdes	cipher_set_keycontext(&state->receive_context, keyin);
2778295367Sdes
2779295367Sdes	if ((r = ssh_packet_set_compress_state(ssh, m)) != 0 ||
2780295367Sdes	    (r = ssh_packet_set_postauth(ssh)) != 0)
2781295367Sdes		return r;
2782295367Sdes
2783295367Sdes	sshbuf_reset(state->input);
2784295367Sdes	sshbuf_reset(state->output);
2785295367Sdes	if ((r = sshbuf_get_string_direct(m, &input, &ilen)) != 0 ||
2786295367Sdes	    (r = sshbuf_get_string_direct(m, &output, &olen)) != 0 ||
2787295367Sdes	    (r = sshbuf_put(state->input, input, ilen)) != 0 ||
2788295367Sdes	    (r = sshbuf_put(state->output, output, olen)) != 0)
2789295367Sdes		return r;
2790295367Sdes
2791295367Sdes	if (sshbuf_len(m))
2792295367Sdes		return SSH_ERR_INVALID_FORMAT;
2793295367Sdes	debug3("%s: done", __func__);
2794295367Sdes	return 0;
2795295367Sdes}
2796295367Sdes
2797295367Sdes/* NEW API */
2798295367Sdes
2799295367Sdes/* put data to the outgoing packet */
2800295367Sdes
2801295367Sdesint
2802295367Sdessshpkt_put(struct ssh *ssh, const void *v, size_t len)
2803295367Sdes{
2804295367Sdes	return sshbuf_put(ssh->state->outgoing_packet, v, len);
2805295367Sdes}
2806295367Sdes
2807295367Sdesint
2808295367Sdessshpkt_putb(struct ssh *ssh, const struct sshbuf *b)
2809295367Sdes{
2810295367Sdes	return sshbuf_putb(ssh->state->outgoing_packet, b);
2811295367Sdes}
2812295367Sdes
2813295367Sdesint
2814295367Sdessshpkt_put_u8(struct ssh *ssh, u_char val)
2815295367Sdes{
2816295367Sdes	return sshbuf_put_u8(ssh->state->outgoing_packet, val);
2817295367Sdes}
2818295367Sdes
2819295367Sdesint
2820295367Sdessshpkt_put_u32(struct ssh *ssh, u_int32_t val)
2821295367Sdes{
2822295367Sdes	return sshbuf_put_u32(ssh->state->outgoing_packet, val);
2823295367Sdes}
2824295367Sdes
2825295367Sdesint
2826295367Sdessshpkt_put_u64(struct ssh *ssh, u_int64_t val)
2827295367Sdes{
2828295367Sdes	return sshbuf_put_u64(ssh->state->outgoing_packet, val);
2829295367Sdes}
2830295367Sdes
2831295367Sdesint
2832295367Sdessshpkt_put_string(struct ssh *ssh, const void *v, size_t len)
2833295367Sdes{
2834295367Sdes	return sshbuf_put_string(ssh->state->outgoing_packet, v, len);
2835295367Sdes}
2836295367Sdes
2837295367Sdesint
2838295367Sdessshpkt_put_cstring(struct ssh *ssh, const void *v)
2839295367Sdes{
2840295367Sdes	return sshbuf_put_cstring(ssh->state->outgoing_packet, v);
2841295367Sdes}
2842295367Sdes
2843295367Sdesint
2844295367Sdessshpkt_put_stringb(struct ssh *ssh, const struct sshbuf *v)
2845295367Sdes{
2846295367Sdes	return sshbuf_put_stringb(ssh->state->outgoing_packet, v);
2847295367Sdes}
2848295367Sdes
2849295367Sdes#ifdef WITH_OPENSSL
2850295367Sdes#ifdef OPENSSL_HAS_ECC
2851295367Sdesint
2852295367Sdessshpkt_put_ec(struct ssh *ssh, const EC_POINT *v, const EC_GROUP *g)
2853295367Sdes{
2854295367Sdes	return sshbuf_put_ec(ssh->state->outgoing_packet, v, g);
2855295367Sdes}
2856295367Sdes#endif /* OPENSSL_HAS_ECC */
2857295367Sdes
2858295367Sdes#ifdef WITH_SSH1
2859295367Sdesint
2860295367Sdessshpkt_put_bignum1(struct ssh *ssh, const BIGNUM *v)
2861295367Sdes{
2862295367Sdes	return sshbuf_put_bignum1(ssh->state->outgoing_packet, v);
2863295367Sdes}
2864295367Sdes#endif /* WITH_SSH1 */
2865295367Sdes
2866295367Sdesint
2867295367Sdessshpkt_put_bignum2(struct ssh *ssh, const BIGNUM *v)
2868295367Sdes{
2869295367Sdes	return sshbuf_put_bignum2(ssh->state->outgoing_packet, v);
2870295367Sdes}
2871295367Sdes#endif /* WITH_OPENSSL */
2872295367Sdes
2873295367Sdes/* fetch data from the incoming packet */
2874295367Sdes
2875295367Sdesint
2876295367Sdessshpkt_get(struct ssh *ssh, void *valp, size_t len)
2877295367Sdes{
2878295367Sdes	return sshbuf_get(ssh->state->incoming_packet, valp, len);
2879295367Sdes}
2880295367Sdes
2881295367Sdesint
2882295367Sdessshpkt_get_u8(struct ssh *ssh, u_char *valp)
2883295367Sdes{
2884295367Sdes	return sshbuf_get_u8(ssh->state->incoming_packet, valp);
2885295367Sdes}
2886295367Sdes
2887295367Sdesint
2888295367Sdessshpkt_get_u32(struct ssh *ssh, u_int32_t *valp)
2889295367Sdes{
2890295367Sdes	return sshbuf_get_u32(ssh->state->incoming_packet, valp);
2891295367Sdes}
2892295367Sdes
2893295367Sdesint
2894295367Sdessshpkt_get_u64(struct ssh *ssh, u_int64_t *valp)
2895295367Sdes{
2896295367Sdes	return sshbuf_get_u64(ssh->state->incoming_packet, valp);
2897295367Sdes}
2898295367Sdes
2899295367Sdesint
2900295367Sdessshpkt_get_string(struct ssh *ssh, u_char **valp, size_t *lenp)
2901295367Sdes{
2902295367Sdes	return sshbuf_get_string(ssh->state->incoming_packet, valp, lenp);
2903295367Sdes}
2904295367Sdes
2905295367Sdesint
2906295367Sdessshpkt_get_string_direct(struct ssh *ssh, const u_char **valp, size_t *lenp)
2907295367Sdes{
2908295367Sdes	return sshbuf_get_string_direct(ssh->state->incoming_packet, valp, lenp);
2909295367Sdes}
2910295367Sdes
2911295367Sdesint
2912295367Sdessshpkt_get_cstring(struct ssh *ssh, char **valp, size_t *lenp)
2913295367Sdes{
2914295367Sdes	return sshbuf_get_cstring(ssh->state->incoming_packet, valp, lenp);
2915295367Sdes}
2916295367Sdes
2917295367Sdes#ifdef WITH_OPENSSL
2918295367Sdes#ifdef OPENSSL_HAS_ECC
2919295367Sdesint
2920295367Sdessshpkt_get_ec(struct ssh *ssh, EC_POINT *v, const EC_GROUP *g)
2921295367Sdes{
2922295367Sdes	return sshbuf_get_ec(ssh->state->incoming_packet, v, g);
2923295367Sdes}
2924295367Sdes#endif /* OPENSSL_HAS_ECC */
2925295367Sdes
2926295367Sdes#ifdef WITH_SSH1
2927295367Sdesint
2928295367Sdessshpkt_get_bignum1(struct ssh *ssh, BIGNUM *v)
2929295367Sdes{
2930295367Sdes	return sshbuf_get_bignum1(ssh->state->incoming_packet, v);
2931295367Sdes}
2932295367Sdes#endif /* WITH_SSH1 */
2933295367Sdes
2934295367Sdesint
2935295367Sdessshpkt_get_bignum2(struct ssh *ssh, BIGNUM *v)
2936295367Sdes{
2937295367Sdes	return sshbuf_get_bignum2(ssh->state->incoming_packet, v);
2938295367Sdes}
2939295367Sdes#endif /* WITH_OPENSSL */
2940295367Sdes
2941295367Sdesint
2942295367Sdessshpkt_get_end(struct ssh *ssh)
2943295367Sdes{
2944295367Sdes	if (sshbuf_len(ssh->state->incoming_packet) > 0)
2945295367Sdes		return SSH_ERR_UNEXPECTED_TRAILING_DATA;
2946295367Sdes	return 0;
2947295367Sdes}
2948295367Sdes
2949295367Sdesconst u_char *
2950295367Sdessshpkt_ptr(struct ssh *ssh, size_t *lenp)
2951295367Sdes{
2952295367Sdes	if (lenp != NULL)
2953295367Sdes		*lenp = sshbuf_len(ssh->state->incoming_packet);
2954295367Sdes	return sshbuf_ptr(ssh->state->incoming_packet);
2955295367Sdes}
2956295367Sdes
2957295367Sdes/* start a new packet */
2958295367Sdes
2959295367Sdesint
2960295367Sdessshpkt_start(struct ssh *ssh, u_char type)
2961295367Sdes{
2962295367Sdes	u_char buf[9];
2963295367Sdes	int len;
2964295367Sdes
2965295367Sdes	DBG(debug("packet_start[%d]", type));
2966295367Sdes	len = compat20 ? 6 : 9;
2967295367Sdes	memset(buf, 0, len - 1);
2968295367Sdes	buf[len - 1] = type;
2969295367Sdes	sshbuf_reset(ssh->state->outgoing_packet);
2970295367Sdes	return sshbuf_put(ssh->state->outgoing_packet, buf, len);
2971295367Sdes}
2972295367Sdes
2973295367Sdes/* send it */
2974295367Sdes
2975295367Sdesint
2976295367Sdessshpkt_send(struct ssh *ssh)
2977295367Sdes{
2978295367Sdes	if (compat20)
2979295367Sdes		return ssh_packet_send2(ssh);
2980295367Sdes	else
2981295367Sdes		return ssh_packet_send1(ssh);
2982295367Sdes}
2983295367Sdes
2984295367Sdesint
2985295367Sdessshpkt_disconnect(struct ssh *ssh, const char *fmt,...)
2986295367Sdes{
2987295367Sdes	char buf[1024];
2988295367Sdes	va_list args;
2989295367Sdes	int r;
2990295367Sdes
2991295367Sdes	va_start(args, fmt);
2992295367Sdes	vsnprintf(buf, sizeof(buf), fmt, args);
2993295367Sdes	va_end(args);
2994295367Sdes
2995295367Sdes	if (compat20) {
2996295367Sdes		if ((r = sshpkt_start(ssh, SSH2_MSG_DISCONNECT)) != 0 ||
2997295367Sdes		    (r = sshpkt_put_u32(ssh, SSH2_DISCONNECT_PROTOCOL_ERROR)) != 0 ||
2998295367Sdes		    (r = sshpkt_put_cstring(ssh, buf)) != 0 ||
2999295367Sdes		    (r = sshpkt_put_cstring(ssh, "")) != 0 ||
3000295367Sdes		    (r = sshpkt_send(ssh)) != 0)
3001295367Sdes			return r;
3002295367Sdes	} else {
3003295367Sdes		if ((r = sshpkt_start(ssh, SSH_MSG_DISCONNECT)) != 0 ||
3004295367Sdes		    (r = sshpkt_put_cstring(ssh, buf)) != 0 ||
3005295367Sdes		    (r = sshpkt_send(ssh)) != 0)
3006295367Sdes			return r;
3007295367Sdes	}
3008295367Sdes	return 0;
3009295367Sdes}
3010295367Sdes
3011295367Sdes/* roundup current message to pad bytes */
3012295367Sdesint
3013295367Sdessshpkt_add_padding(struct ssh *ssh, u_char pad)
3014295367Sdes{
3015295367Sdes	ssh->state->extra_pad = pad;
3016295367Sdes	return 0;
3017295367Sdes}
3018