1323136Sdes/* $OpenBSD: packet.c,v 1.247 2017/03/11 13:07:35 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"
41263691Sdes__RCSID("$FreeBSD: stable/11/crypto/openssh/packet.c 323136 2017-09-02 23:39:51Z des $");
42323134Sdes
43162852Sdes#include <sys/types.h>
44124208Sdes#include "openbsd-compat/sys-queue.h"
45162852Sdes#include <sys/socket.h>
46162852Sdes#ifdef HAVE_SYS_TIME_H
47162852Sdes# include <sys/time.h>
48162852Sdes#endif
49124208Sdes
50162852Sdes#include <netinet/in.h>
51162852Sdes#include <netinet/ip.h>
52162852Sdes#include <arpa/inet.h>
53162852Sdes
54162852Sdes#include <errno.h>
55323129Sdes#include <netdb.h>
56162852Sdes#include <stdarg.h>
57162852Sdes#include <stdio.h>
58162852Sdes#include <stdlib.h>
59162852Sdes#include <string.h>
60162852Sdes#include <unistd.h>
61294332Sdes#include <limits.h>
62162852Sdes#include <signal.h>
63255767Sdes#include <time.h>
64162852Sdes
65294332Sdes#include <zlib.h>
66294332Sdes
67294332Sdes#include "buffer.h"	/* typedefs XXX */
68294332Sdes#include "key.h"	/* typedefs XXX */
69294332Sdes
7057429Smarkm#include "xmalloc.h"
7157429Smarkm#include "crc32.h"
7257429Smarkm#include "deattack.h"
7360573Skris#include "compat.h"
7476259Sgreen#include "ssh1.h"
7560573Skris#include "ssh2.h"
7669587Sgreen#include "cipher.h"
77294332Sdes#include "sshkey.h"
7860573Skris#include "kex.h"
79294332Sdes#include "digest.h"
8076259Sgreen#include "mac.h"
8176259Sgreen#include "log.h"
8276259Sgreen#include "canohost.h"
8392555Sdes#include "misc.h"
84294328Sdes#include "channels.h"
8598675Sdes#include "ssh.h"
86294332Sdes#include "packet.h"
87294328Sdes#include "ssherr.h"
88294332Sdes#include "sshbuf.h"
89305476Slidl#include "blacklist_client.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;
109294332Sdes	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. */
126323134Sdes	struct sshcipher_ctx *receive_context;
12757429Smarkm
128197679Sdes	/* Encryption context for sending data.  Only used for encryption. */
129323134Sdes	struct sshcipher_ctx *send_context;
13057429Smarkm
131197679Sdes	/* Buffer for raw input data from the socket. */
132294332Sdes	struct sshbuf *input;
13357429Smarkm
134197679Sdes	/* Buffer for raw output data going to the socket. */
135294332Sdes	struct sshbuf *output;
13657429Smarkm
137197679Sdes	/* Buffer for the partial outgoing packet being constructed. */
138294332Sdes	struct sshbuf *outgoing_packet;
13957429Smarkm
140197679Sdes	/* Buffer for the incoming packet currently being processed. */
141294332Sdes	struct sshbuf *incoming_packet;
14257429Smarkm
143197679Sdes	/* Scratch buffer for packet compression/decompression. */
144294332Sdes	struct sshbuf *compression_buffer;
14557429Smarkm
146294332Sdes	/* Incoming/outgoing compression dictionaries */
147294332Sdes	z_stream compression_in_stream;
148294332Sdes	z_stream compression_out_stream;
149294332Sdes	int compression_in_started;
150294332Sdes	int compression_out_started;
151294332Sdes	int compression_in_failures;
152294332Sdes	int compression_out_failures;
153294332Sdes
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 */
181294332Sdes	struct newkeys *newkeys[MODE_MAX];
182197679Sdes	struct packet_state p_read, p_send;
18398675Sdes
184255767Sdes	/* Volume-based rekeying */
185296633Sdes	u_int64_t max_blocks_in, max_blocks_out, rekey_limit;
18660573Skris
187255767Sdes	/* Time-based rekeying */
188294332Sdes	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;
200323129Sdes	size_t packet_discard_mac_already;
201294332Sdes	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
209323134Sdes	/* Used in ssh_packet_send_mux() */
210323134Sdes	int mux;
211323134Sdes
212197679Sdes	/* Used in packet_set_interactive */
213197679Sdes	int set_interactive_called;
214197679Sdes
215197679Sdes	/* Used in packet_set_maxsize */
216197679Sdes	int set_maxsize_called;
217197679Sdes
218294332Sdes	/* One-off warning about weak ciphers */
219294332Sdes	int cipher_warning_done;
220294332Sdes
221294332Sdes	/* SSH1 CRC compensation attack detector */
222294332Sdes	struct deattack_ctx deattack;
223294332Sdes
224323134Sdes	/* Hook for fuzzing inbound packets */
225323134Sdes	ssh_packet_hook_fn *hook_in;
226323134Sdes	void *hook_in_ctx;
227323134Sdes
228197679Sdes	TAILQ_HEAD(, packet) outgoing;
229124208Sdes};
230124208Sdes
231294332Sdesstruct ssh *
232294332Sdesssh_alloc_session_state(void)
233197679Sdes{
234294332Sdes	struct ssh *ssh = NULL;
235294332Sdes	struct session_state *state = NULL;
236197679Sdes
237294332Sdes	if ((ssh = calloc(1, sizeof(*ssh))) == NULL ||
238294332Sdes	    (state = calloc(1, sizeof(*state))) == NULL ||
239294332Sdes	    (state->input = sshbuf_new()) == NULL ||
240294332Sdes	    (state->output = sshbuf_new()) == NULL ||
241294332Sdes	    (state->outgoing_packet = sshbuf_new()) == NULL ||
242294332Sdes	    (state->incoming_packet = sshbuf_new()) == NULL)
243294332Sdes		goto fail;
244294332Sdes	TAILQ_INIT(&state->outgoing);
245294332Sdes	TAILQ_INIT(&ssh->private_keys);
246294332Sdes	TAILQ_INIT(&ssh->public_keys);
247294332Sdes	state->connection_in = -1;
248294332Sdes	state->connection_out = -1;
249294332Sdes	state->max_packet_size = 32768;
250294332Sdes	state->packet_timeout_ms = -1;
251294332Sdes	state->p_send.packets = state->p_read.packets = 0;
252294332Sdes	state->initialized = 1;
253294332Sdes	/*
254294332Sdes	 * ssh_packet_send2() needs to queue packets until
255294332Sdes	 * we've done the initial key exchange.
256294332Sdes	 */
257294332Sdes	state->rekeying = 1;
258294332Sdes	ssh->state = state;
259294332Sdes	return ssh;
260294332Sdes fail:
261294332Sdes	if (state) {
262294332Sdes		sshbuf_free(state->input);
263294332Sdes		sshbuf_free(state->output);
264294332Sdes		sshbuf_free(state->incoming_packet);
265294332Sdes		sshbuf_free(state->outgoing_packet);
266294332Sdes		free(state);
267294332Sdes	}
268294332Sdes	free(ssh);
269294332Sdes	return NULL;
270197679Sdes}
271197679Sdes
272323134Sdesvoid
273323134Sdesssh_packet_set_input_hook(struct ssh *ssh, ssh_packet_hook_fn *hook, void *ctx)
274323134Sdes{
275323134Sdes	ssh->state->hook_in = hook;
276323134Sdes	ssh->state->hook_in_ctx = ctx;
277323134Sdes}
278323134Sdes
279296633Sdes/* Returns nonzero if rekeying is in progress */
280296633Sdesint
281296633Sdesssh_packet_is_rekeying(struct ssh *ssh)
282296633Sdes{
283296633Sdes	return compat20 &&
284296633Sdes	    (ssh->state->rekeying || (ssh->kex != NULL && ssh->kex->done == 0));
285296633Sdes}
286296633Sdes
28757429Smarkm/*
28857429Smarkm * Sets the descriptors used for communication.  Disables encryption until
28957429Smarkm * packet_set_encryption_key is called.
29057429Smarkm */
291294332Sdesstruct ssh *
292294332Sdesssh_packet_set_connection(struct ssh *ssh, int fd_in, int fd_out)
29357429Smarkm{
294294332Sdes	struct session_state *state;
295294332Sdes	const struct sshcipher *none = cipher_by_name("none");
296294328Sdes	int r;
297106121Sdes
298294332Sdes	if (none == NULL) {
299294332Sdes		error("%s: cannot load cipher 'none'", __func__);
300294332Sdes		return NULL;
301294332Sdes	}
302294332Sdes	if (ssh == NULL)
303294332Sdes		ssh = ssh_alloc_session_state();
304294332Sdes	if (ssh == NULL) {
305294332Sdes		error("%s: cound not allocate state", __func__);
306294332Sdes		return NULL;
307294332Sdes	}
308294332Sdes	state = ssh->state;
309294332Sdes	state->connection_in = fd_in;
310294332Sdes	state->connection_out = fd_out;
311294332Sdes	if ((r = cipher_init(&state->send_context, none,
312294328Sdes	    (const u_char *)"", 0, NULL, 0, CIPHER_ENCRYPT)) != 0 ||
313294332Sdes	    (r = cipher_init(&state->receive_context, none,
314294332Sdes	    (const u_char *)"", 0, NULL, 0, CIPHER_DECRYPT)) != 0) {
315294332Sdes		error("%s: cipher_init failed: %s", __func__, ssh_err(r));
316323129Sdes		free(ssh); /* XXX need ssh_free_session_state? */
317294332Sdes		return NULL;
31857429Smarkm	}
319294332Sdes	state->newkeys[MODE_IN] = state->newkeys[MODE_OUT] = NULL;
320294332Sdes	deattack_init(&state->deattack);
321294332Sdes	/*
322294332Sdes	 * Cache the IP address of the remote connection for use in error
323294332Sdes	 * messages that might be generated after the connection has closed.
324294332Sdes	 */
325294332Sdes	(void)ssh_remote_ipaddr(ssh);
326294332Sdes	return ssh;
32757429Smarkm}
32857429Smarkm
329181111Sdesvoid
330294332Sdesssh_packet_set_timeout(struct ssh *ssh, int timeout, int count)
331181111Sdes{
332294332Sdes	struct session_state *state = ssh->state;
333294332Sdes
334240075Sdes	if (timeout <= 0 || count <= 0) {
335294332Sdes		state->packet_timeout_ms = -1;
336181111Sdes		return;
337181111Sdes	}
338181111Sdes	if ((INT_MAX / 1000) / count < timeout)
339294332Sdes		state->packet_timeout_ms = INT_MAX;
340181111Sdes	else
341294332Sdes		state->packet_timeout_ms = timeout * count * 1000;
342181111Sdes}
343181111Sdes
344323134Sdesvoid
345323134Sdesssh_packet_set_mux(struct ssh *ssh)
346323134Sdes{
347323134Sdes	ssh->state->mux = 1;
348323134Sdes	ssh->state->rekeying = 0;
349323134Sdes}
350323134Sdes
351294332Sdesint
352323134Sdesssh_packet_get_mux(struct ssh *ssh)
353323134Sdes{
354323134Sdes	return ssh->state->mux;
355323134Sdes}
356323134Sdes
357323134Sdesint
358323136Sdesssh_packet_set_log_preamble(struct ssh *ssh, const char *fmt, ...)
359323136Sdes{
360323136Sdes	va_list args;
361323136Sdes	int r;
362323136Sdes
363323136Sdes	free(ssh->log_preamble);
364323136Sdes	if (fmt == NULL)
365323136Sdes		ssh->log_preamble = NULL;
366323136Sdes	else {
367323136Sdes		va_start(args, fmt);
368323136Sdes		r = vasprintf(&ssh->log_preamble, fmt, args);
369323136Sdes		va_end(args);
370323136Sdes		if (r < 0 || ssh->log_preamble == NULL)
371323136Sdes			return SSH_ERR_ALLOC_FAIL;
372323136Sdes	}
373323136Sdes	return 0;
374323136Sdes}
375323136Sdes
376323136Sdesint
377294332Sdesssh_packet_stop_discard(struct ssh *ssh)
378192595Sdes{
379294332Sdes	struct session_state *state = ssh->state;
380294332Sdes	int r;
381294332Sdes
382294332Sdes	if (state->packet_discard_mac) {
383192595Sdes		char buf[1024];
384323129Sdes		size_t dlen = PACKET_MAX_SIZE;
385294332Sdes
386323129Sdes		if (dlen > state->packet_discard_mac_already)
387323129Sdes			dlen -= state->packet_discard_mac_already;
388192595Sdes		memset(buf, 'a', sizeof(buf));
389323129Sdes		while (sshbuf_len(state->incoming_packet) < dlen)
390294332Sdes			if ((r = sshbuf_put(state->incoming_packet, buf,
391294332Sdes			    sizeof(buf))) != 0)
392294332Sdes				return r;
393294332Sdes		(void) mac_compute(state->packet_discard_mac,
394294332Sdes		    state->p_read.seqnr,
395323129Sdes		    sshbuf_ptr(state->incoming_packet), dlen,
396294332Sdes		    NULL, 0);
397192595Sdes	}
398296633Sdes	logit("Finished discarding for %.200s port %d",
399296633Sdes	    ssh_remote_ipaddr(ssh), ssh_remote_port(ssh));
400294332Sdes	return SSH_ERR_MAC_INVALID;
401192595Sdes}
402192595Sdes
403294332Sdesstatic int
404294332Sdesssh_packet_start_discard(struct ssh *ssh, struct sshenc *enc,
405323129Sdes    struct sshmac *mac, size_t mac_already, u_int discard)
406192595Sdes{
407294332Sdes	struct session_state *state = ssh->state;
408294332Sdes	int r;
409294332Sdes
410294332Sdes	if (enc == NULL || !cipher_is_cbc(enc->cipher) || (mac && mac->etm)) {
411294332Sdes		if ((r = sshpkt_disconnect(ssh, "Packet corrupt")) != 0)
412294332Sdes			return r;
413294332Sdes		return SSH_ERR_MAC_INVALID;
414294332Sdes	}
415323129Sdes	/*
416323129Sdes	 * Record number of bytes over which the mac has already
417323129Sdes	 * been computed in order to minimize timing attacks.
418323129Sdes	 */
419323129Sdes	if (mac && mac->enabled) {
420294332Sdes		state->packet_discard_mac = mac;
421323129Sdes		state->packet_discard_mac_already = mac_already;
422323129Sdes	}
423323129Sdes	if (sshbuf_len(state->input) >= discard)
424323129Sdes		return ssh_packet_stop_discard(ssh);
425294332Sdes	state->packet_discard = discard - sshbuf_len(state->input);
426294332Sdes	return 0;
427192595Sdes}
428192595Sdes
42957429Smarkm/* Returns 1 if remote host is connected via socket, 0 if not. */
43057429Smarkm
43157429Smarkmint
432294332Sdesssh_packet_connection_is_on_socket(struct ssh *ssh)
43357429Smarkm{
434294332Sdes	struct session_state *state = ssh->state;
43557429Smarkm	struct sockaddr_storage from, to;
43657429Smarkm	socklen_t fromlen, tolen;
43757429Smarkm
438323129Sdes	if (state->connection_in == -1 || state->connection_out == -1)
439323129Sdes		return 0;
440323129Sdes
44157429Smarkm	/* filedescriptors in and out are the same, so it's a socket */
442294332Sdes	if (state->connection_in == state->connection_out)
44357429Smarkm		return 1;
44457429Smarkm	fromlen = sizeof(from);
44557429Smarkm	memset(&from, 0, sizeof(from));
446294332Sdes	if (getpeername(state->connection_in, (struct sockaddr *)&from,
447197679Sdes	    &fromlen) < 0)
44857429Smarkm		return 0;
44957429Smarkm	tolen = sizeof(to);
45057429Smarkm	memset(&to, 0, sizeof(to));
451294332Sdes	if (getpeername(state->connection_out, (struct sockaddr *)&to,
452197679Sdes	    &tolen) < 0)
45357429Smarkm		return 0;
45457429Smarkm	if (fromlen != tolen || memcmp(&from, &to, fromlen) != 0)
45557429Smarkm		return 0;
45657429Smarkm	if (from.ss_family != AF_INET && from.ss_family != AF_INET6)
45757429Smarkm		return 0;
45857429Smarkm	return 1;
45957429Smarkm}
46057429Smarkm
46198675Sdesvoid
462294332Sdesssh_packet_get_bytes(struct ssh *ssh, u_int64_t *ibytes, u_int64_t *obytes)
46398675Sdes{
464294332Sdes	if (ibytes)
465294332Sdes		*ibytes = ssh->state->p_read.bytes;
466294332Sdes	if (obytes)
467294332Sdes		*obytes = ssh->state->p_send.bytes;
46898675Sdes}
46998675Sdes
47098675Sdesint
471294332Sdesssh_packet_connection_af(struct ssh *ssh)
47298675Sdes{
47357429Smarkm	struct sockaddr_storage to;
47457429Smarkm	socklen_t tolen = sizeof(to);
47557429Smarkm
47657429Smarkm	memset(&to, 0, sizeof(to));
477294332Sdes	if (getsockname(ssh->state->connection_out, (struct sockaddr *)&to,
478197679Sdes	    &tolen) < 0)
47957429Smarkm		return 0;
48098937Sdes#ifdef IPV4_IN_IPV6
481126274Sdes	if (to.ss_family == AF_INET6 &&
48298937Sdes	    IN6_IS_ADDR_V4MAPPED(&((struct sockaddr_in6 *)&to)->sin6_addr))
483226046Sdes		return AF_INET;
48498937Sdes#endif
485226046Sdes	return to.ss_family;
48657429Smarkm}
48757429Smarkm
48857429Smarkm/* Sets the connection into non-blocking mode. */
48957429Smarkm
49057429Smarkmvoid
491294332Sdesssh_packet_set_nonblocking(struct ssh *ssh)
49257429Smarkm{
49357429Smarkm	/* Set the socket into non-blocking mode. */
494294332Sdes	set_nonblock(ssh->state->connection_in);
49557429Smarkm
496294332Sdes	if (ssh->state->connection_out != ssh->state->connection_in)
497294332Sdes		set_nonblock(ssh->state->connection_out);
49857429Smarkm}
49957429Smarkm
50057429Smarkm/* Returns the socket used for reading. */
50157429Smarkm
50257429Smarkmint
503294332Sdesssh_packet_get_connection_in(struct ssh *ssh)
50457429Smarkm{
505294332Sdes	return ssh->state->connection_in;
50657429Smarkm}
50757429Smarkm
50857429Smarkm/* Returns the descriptor used for writing. */
50957429Smarkm
51057429Smarkmint
511294332Sdesssh_packet_get_connection_out(struct ssh *ssh)
51257429Smarkm{
513294332Sdes	return ssh->state->connection_out;
51457429Smarkm}
51557429Smarkm
516294332Sdes/*
517294332Sdes * Returns the IP-address of the remote host as a string.  The returned
518294332Sdes * string must not be freed.
519294332Sdes */
520294332Sdes
521294332Sdesconst char *
522294332Sdesssh_remote_ipaddr(struct ssh *ssh)
523294332Sdes{
524296633Sdes	const int sock = ssh->state->connection_in;
525296633Sdes
526294332Sdes	/* Check whether we have cached the ipaddr. */
527296633Sdes	if (ssh->remote_ipaddr == NULL) {
528296633Sdes		if (ssh_packet_connection_is_on_socket(ssh)) {
529296633Sdes			ssh->remote_ipaddr = get_peer_ipaddr(sock);
530323129Sdes			ssh->remote_port = get_peer_port(sock);
531323129Sdes			ssh->local_ipaddr = get_local_ipaddr(sock);
532323129Sdes			ssh->local_port = get_local_port(sock);
533296633Sdes		} else {
534296633Sdes			ssh->remote_ipaddr = strdup("UNKNOWN");
535323129Sdes			ssh->remote_port = 65535;
536323129Sdes			ssh->local_ipaddr = strdup("UNKNOWN");
537323129Sdes			ssh->local_port = 65535;
538296633Sdes		}
539296633Sdes	}
540294332Sdes	return ssh->remote_ipaddr;
541294332Sdes}
542294332Sdes
543296633Sdes/* Returns the port number of the remote host. */
544296633Sdes
545296633Sdesint
546296633Sdesssh_remote_port(struct ssh *ssh)
547296633Sdes{
548296633Sdes	(void)ssh_remote_ipaddr(ssh); /* Will lookup and cache. */
549296633Sdes	return ssh->remote_port;
550296633Sdes}
551296633Sdes
552323129Sdes/*
553323129Sdes * Returns the IP-address of the local host as a string.  The returned
554323129Sdes * string must not be freed.
555323129Sdes */
556323129Sdes
557323129Sdesconst char *
558323129Sdesssh_local_ipaddr(struct ssh *ssh)
559323129Sdes{
560323129Sdes	(void)ssh_remote_ipaddr(ssh); /* Will lookup and cache. */
561323129Sdes	return ssh->local_ipaddr;
562323129Sdes}
563323129Sdes
564323129Sdes/* Returns the port number of the local host. */
565323129Sdes
566323129Sdesint
567323129Sdesssh_local_port(struct ssh *ssh)
568323129Sdes{
569323129Sdes	(void)ssh_remote_ipaddr(ssh); /* Will lookup and cache. */
570323129Sdes	return ssh->local_port;
571323129Sdes}
572323129Sdes
57357429Smarkm/* Closes the connection and clears and frees internal data structures. */
57457429Smarkm
57557429Smarkmvoid
576294332Sdesssh_packet_close(struct ssh *ssh)
57757429Smarkm{
578294332Sdes	struct session_state *state = ssh->state;
579294332Sdes	u_int mode;
580294332Sdes
581294332Sdes	if (!state->initialized)
58257429Smarkm		return;
583294332Sdes	state->initialized = 0;
584294332Sdes	if (state->connection_in == state->connection_out) {
585294332Sdes		shutdown(state->connection_out, SHUT_RDWR);
586294332Sdes		close(state->connection_out);
58757429Smarkm	} else {
588294332Sdes		close(state->connection_in);
589294332Sdes		close(state->connection_out);
59057429Smarkm	}
591294332Sdes	sshbuf_free(state->input);
592294332Sdes	sshbuf_free(state->output);
593294332Sdes	sshbuf_free(state->outgoing_packet);
594294332Sdes	sshbuf_free(state->incoming_packet);
595294332Sdes	for (mode = 0; mode < MODE_MAX; mode++)
596294332Sdes		kex_free_newkeys(state->newkeys[mode]);
597294332Sdes	if (state->compression_buffer) {
598294332Sdes		sshbuf_free(state->compression_buffer);
599294332Sdes		if (state->compression_out_started) {
600294332Sdes			z_streamp stream = &state->compression_out_stream;
601294332Sdes			debug("compress outgoing: "
602294332Sdes			    "raw data %llu, compressed %llu, factor %.2f",
603294332Sdes				(unsigned long long)stream->total_in,
604294332Sdes				(unsigned long long)stream->total_out,
605294332Sdes				stream->total_in == 0 ? 0.0 :
606294332Sdes				(double) stream->total_out / stream->total_in);
607294332Sdes			if (state->compression_out_failures == 0)
608294332Sdes				deflateEnd(stream);
609294332Sdes		}
610294332Sdes		if (state->compression_in_started) {
611294332Sdes			z_streamp stream = &state->compression_out_stream;
612294332Sdes			debug("compress incoming: "
613294332Sdes			    "raw data %llu, compressed %llu, factor %.2f",
614294332Sdes			    (unsigned long long)stream->total_out,
615294332Sdes			    (unsigned long long)stream->total_in,
616294332Sdes			    stream->total_out == 0 ? 0.0 :
617294332Sdes			    (double) stream->total_in / stream->total_out);
618294332Sdes			if (state->compression_in_failures == 0)
619294332Sdes				inflateEnd(stream);
620294332Sdes		}
62157429Smarkm	}
622323134Sdes	cipher_free(state->send_context);
623323134Sdes	cipher_free(state->receive_context);
624323134Sdes	state->send_context = state->receive_context = NULL;
625296633Sdes	free(ssh->remote_ipaddr);
626296633Sdes	ssh->remote_ipaddr = NULL;
627294332Sdes	free(ssh->state);
628294332Sdes	ssh->state = NULL;
62957429Smarkm}
63057429Smarkm
63157429Smarkm/* Sets remote side protocol flags. */
63257429Smarkm
63357429Smarkmvoid
634294332Sdesssh_packet_set_protocol_flags(struct ssh *ssh, u_int protocol_flags)
63557429Smarkm{
636294332Sdes	ssh->state->remote_protocol_flags = protocol_flags;
63757429Smarkm}
63857429Smarkm
63957429Smarkm/* Returns the remote protocol flags set earlier by the above function. */
64057429Smarkm
64176259Sgreenu_int
642294332Sdesssh_packet_get_protocol_flags(struct ssh *ssh)
64357429Smarkm{
644294332Sdes	return ssh->state->remote_protocol_flags;
64557429Smarkm}
64657429Smarkm
64757429Smarkm/*
64857429Smarkm * Starts packet compression from the next packet on in both directions.
64957429Smarkm * Level is compression level 1 (fastest) - 9 (slow, best) as in gzip.
65057429Smarkm */
65157429Smarkm
652294332Sdesstatic int
653294332Sdesssh_packet_init_compression(struct ssh *ssh)
65476259Sgreen{
655294332Sdes	if (!ssh->state->compression_buffer &&
656294332Sdes	   ((ssh->state->compression_buffer = sshbuf_new()) == NULL))
657294332Sdes		return SSH_ERR_ALLOC_FAIL;
658294332Sdes	return 0;
65976259Sgreen}
66076259Sgreen
661294332Sdesstatic int
662294332Sdesstart_compression_out(struct ssh *ssh, int level)
66357429Smarkm{
664294332Sdes	if (level < 1 || level > 9)
665294332Sdes		return SSH_ERR_INVALID_ARGUMENT;
666294332Sdes	debug("Enabling compression at level %d.", level);
667294332Sdes	if (ssh->state->compression_out_started == 1)
668294332Sdes		deflateEnd(&ssh->state->compression_out_stream);
669294332Sdes	switch (deflateInit(&ssh->state->compression_out_stream, level)) {
670294332Sdes	case Z_OK:
671294332Sdes		ssh->state->compression_out_started = 1;
672294332Sdes		break;
673294332Sdes	case Z_MEM_ERROR:
674294332Sdes		return SSH_ERR_ALLOC_FAIL;
675294332Sdes	default:
676294332Sdes		return SSH_ERR_INTERNAL_ERROR;
677294332Sdes	}
678294332Sdes	return 0;
67957429Smarkm}
68057429Smarkm
681294332Sdesstatic int
682294332Sdesstart_compression_in(struct ssh *ssh)
683294332Sdes{
684294332Sdes	if (ssh->state->compression_in_started == 1)
685294332Sdes		inflateEnd(&ssh->state->compression_in_stream);
686294332Sdes	switch (inflateInit(&ssh->state->compression_in_stream)) {
687294332Sdes	case Z_OK:
688294332Sdes		ssh->state->compression_in_started = 1;
689294332Sdes		break;
690294332Sdes	case Z_MEM_ERROR:
691294332Sdes		return SSH_ERR_ALLOC_FAIL;
692294332Sdes	default:
693294332Sdes		return SSH_ERR_INTERNAL_ERROR;
694294332Sdes	}
695294332Sdes	return 0;
696294332Sdes}
69798675Sdes
698294332Sdesint
699294332Sdesssh_packet_start_compression(struct ssh *ssh, int level)
70057429Smarkm{
701294328Sdes	int r;
702106121Sdes
703294332Sdes	if (ssh->state->packet_compression && !compat20)
704294332Sdes		return SSH_ERR_INTERNAL_ERROR;
705294332Sdes	ssh->state->packet_compression = 1;
706294332Sdes	if ((r = ssh_packet_init_compression(ssh)) != 0 ||
707294332Sdes	    (r = start_compression_in(ssh)) != 0 ||
708294332Sdes	    (r = start_compression_out(ssh, level)) != 0)
709294332Sdes		return r;
710294332Sdes	return 0;
71157429Smarkm}
71257429Smarkm
713294332Sdes/* XXX remove need for separate compression buffer */
714294332Sdesstatic int
715294332Sdescompress_buffer(struct ssh *ssh, struct sshbuf *in, struct sshbuf *out)
71698675Sdes{
717294332Sdes	u_char buf[4096];
718294332Sdes	int r, status;
71998675Sdes
720294332Sdes	if (ssh->state->compression_out_started != 1)
721294332Sdes		return SSH_ERR_INTERNAL_ERROR;
72257429Smarkm
723294332Sdes	/* This case is not handled below. */
724294332Sdes	if (sshbuf_len(in) == 0)
725294332Sdes		return 0;
726294332Sdes
727294332Sdes	/* Input is the contents of the input buffer. */
728294332Sdes	if ((ssh->state->compression_out_stream.next_in =
729294332Sdes	    sshbuf_mutable_ptr(in)) == NULL)
730294332Sdes		return SSH_ERR_INTERNAL_ERROR;
731294332Sdes	ssh->state->compression_out_stream.avail_in = sshbuf_len(in);
732294332Sdes
733294332Sdes	/* Loop compressing until deflate() returns with avail_out != 0. */
734294332Sdes	do {
735294332Sdes		/* Set up fixed-size output buffer. */
736294332Sdes		ssh->state->compression_out_stream.next_out = buf;
737294332Sdes		ssh->state->compression_out_stream.avail_out = sizeof(buf);
738294332Sdes
739294332Sdes		/* Compress as much data into the buffer as possible. */
740294332Sdes		status = deflate(&ssh->state->compression_out_stream,
741294332Sdes		    Z_PARTIAL_FLUSH);
742294332Sdes		switch (status) {
743294332Sdes		case Z_MEM_ERROR:
744294332Sdes			return SSH_ERR_ALLOC_FAIL;
745294332Sdes		case Z_OK:
746294332Sdes			/* Append compressed data to output_buffer. */
747294332Sdes			if ((r = sshbuf_put(out, buf, sizeof(buf) -
748294332Sdes			    ssh->state->compression_out_stream.avail_out)) != 0)
749294332Sdes				return r;
750294332Sdes			break;
751294332Sdes		case Z_STREAM_ERROR:
752294332Sdes		default:
753294332Sdes			ssh->state->compression_out_failures++;
754294332Sdes			return SSH_ERR_INVALID_FORMAT;
755294332Sdes		}
756294332Sdes	} while (ssh->state->compression_out_stream.avail_out == 0);
757294332Sdes	return 0;
75857429Smarkm}
75957429Smarkm
760294332Sdesstatic int
761294332Sdesuncompress_buffer(struct ssh *ssh, struct sshbuf *in, struct sshbuf *out)
76257429Smarkm{
763294332Sdes	u_char buf[4096];
764294332Sdes	int r, status;
765106121Sdes
766294332Sdes	if (ssh->state->compression_in_started != 1)
767294332Sdes		return SSH_ERR_INTERNAL_ERROR;
768162852Sdes
769294332Sdes	if ((ssh->state->compression_in_stream.next_in =
770294332Sdes	    sshbuf_mutable_ptr(in)) == NULL)
771294332Sdes		return SSH_ERR_INTERNAL_ERROR;
772294332Sdes	ssh->state->compression_in_stream.avail_in = sshbuf_len(in);
773294332Sdes
774294332Sdes	for (;;) {
775294332Sdes		/* Set up fixed-size output buffer. */
776294332Sdes		ssh->state->compression_in_stream.next_out = buf;
777294332Sdes		ssh->state->compression_in_stream.avail_out = sizeof(buf);
778294332Sdes
779294332Sdes		status = inflate(&ssh->state->compression_in_stream,
780294332Sdes		    Z_PARTIAL_FLUSH);
781294332Sdes		switch (status) {
782294332Sdes		case Z_OK:
783294332Sdes			if ((r = sshbuf_put(out, buf, sizeof(buf) -
784294332Sdes			    ssh->state->compression_in_stream.avail_out)) != 0)
785294332Sdes				return r;
786294332Sdes			break;
787294332Sdes		case Z_BUF_ERROR:
788294332Sdes			/*
789294332Sdes			 * Comments in zlib.h say that we should keep calling
790294332Sdes			 * inflate() until we get an error.  This appears to
791294332Sdes			 * be the error that we get.
792294332Sdes			 */
793294332Sdes			return 0;
794294332Sdes		case Z_DATA_ERROR:
795294332Sdes			return SSH_ERR_INVALID_FORMAT;
796294332Sdes		case Z_MEM_ERROR:
797294332Sdes			return SSH_ERR_ALLOC_FAIL;
798294332Sdes		case Z_STREAM_ERROR:
799294332Sdes		default:
800294332Sdes			ssh->state->compression_in_failures++;
801294332Sdes			return SSH_ERR_INTERNAL_ERROR;
802294332Sdes		}
803294332Sdes	}
804294332Sdes	/* NOTREACHED */
80557429Smarkm}
806162852Sdes
807294332Sdes/*
808294332Sdes * Causes any further packets to be encrypted using the given key.  The same
809294332Sdes * key is used for both sending and reception.  However, both directions are
810294332Sdes * encrypted independently of each other.
811294332Sdes */
812294332Sdes
81360573Skrisvoid
814294332Sdesssh_packet_set_encryption_key(struct ssh *ssh, const u_char *key, u_int keylen, int number)
81560573Skris{
816294336Sdes#ifndef WITH_SSH1
817294336Sdes	fatal("no SSH protocol 1 support");
818294336Sdes#else /* WITH_SSH1 */
819294332Sdes	struct session_state *state = ssh->state;
820294332Sdes	const struct sshcipher *cipher = cipher_by_number(number);
821294332Sdes	int r;
822294332Sdes	const char *wmsg;
82357429Smarkm
824294332Sdes	if (cipher == NULL)
825294332Sdes		fatal("%s: unknown cipher number %d", __func__, number);
826294332Sdes	if (keylen < 20)
827294332Sdes		fatal("%s: keylen too small: %d", __func__, keylen);
828294332Sdes	if (keylen > SSH_SESSION_KEY_LENGTH)
829294332Sdes		fatal("%s: keylen too big: %d", __func__, keylen);
830294332Sdes	memcpy(state->ssh1_key, key, keylen);
831294332Sdes	state->ssh1_keylen = keylen;
832294332Sdes	if ((r = cipher_init(&state->send_context, cipher, key, keylen,
833294332Sdes	    NULL, 0, CIPHER_ENCRYPT)) != 0 ||
834294332Sdes	    (r = cipher_init(&state->receive_context, cipher, key, keylen,
835294332Sdes	    NULL, 0, CIPHER_DECRYPT) != 0))
836294332Sdes		fatal("%s: cipher_init failed: %s", __func__, ssh_err(r));
837294332Sdes	if (!state->cipher_warning_done &&
838323134Sdes	    ((wmsg = cipher_warning_message(state->send_context)) != NULL ||
839323134Sdes	    (wmsg = cipher_warning_message(state->send_context)) != NULL)) {
840294332Sdes		error("Warning: %s", wmsg);
841294332Sdes		state->cipher_warning_done = 1;
842294332Sdes	}
843294332Sdes#endif /* WITH_SSH1 */
844221420Sdes}
845221420Sdes
84657429Smarkm/*
84757429Smarkm * Finalizes and sends the packet.  If the encryption key has been set,
84857429Smarkm * encrypts the packet before sending.
84957429Smarkm */
85057429Smarkm
851294332Sdesint
852294332Sdesssh_packet_send1(struct ssh *ssh)
85357429Smarkm{
854294332Sdes	struct session_state *state = ssh->state;
85592555Sdes	u_char buf[8], *cp;
856294332Sdes	int r, padding, len;
85776259Sgreen	u_int checksum;
85857429Smarkm
85957429Smarkm	/*
86057429Smarkm	 * If using packet compression, compress the payload of the outgoing
86157429Smarkm	 * packet.
86257429Smarkm	 */
863294332Sdes	if (state->packet_compression) {
864294332Sdes		sshbuf_reset(state->compression_buffer);
86557429Smarkm		/* Skip padding. */
866294332Sdes		if ((r = sshbuf_consume(state->outgoing_packet, 8)) != 0)
867294332Sdes			goto out;
86857429Smarkm		/* padding */
869294332Sdes		if ((r = sshbuf_put(state->compression_buffer,
870294332Sdes		    "\0\0\0\0\0\0\0\0", 8)) != 0)
871294332Sdes			goto out;
872294332Sdes		if ((r = compress_buffer(ssh, state->outgoing_packet,
873294332Sdes		    state->compression_buffer)) != 0)
874294332Sdes			goto out;
875294332Sdes		sshbuf_reset(state->outgoing_packet);
876294332Sdes                if ((r = sshbuf_putb(state->outgoing_packet,
877294332Sdes                    state->compression_buffer)) != 0)
878294332Sdes			goto out;
87957429Smarkm	}
88057429Smarkm	/* Compute packet length without padding (add checksum, remove padding). */
881294332Sdes	len = sshbuf_len(state->outgoing_packet) + 4 - 8;
88257429Smarkm
88360573Skris	/* Insert padding. Initialized to zero in packet_start1() */
88457429Smarkm	padding = 8 - len % 8;
885323134Sdes	if (!cipher_ctx_is_plaintext(state->send_context)) {
886294332Sdes		cp = sshbuf_mutable_ptr(state->outgoing_packet);
887294332Sdes		if (cp == NULL) {
888294332Sdes			r = SSH_ERR_INTERNAL_ERROR;
889294332Sdes			goto out;
89057429Smarkm		}
891294332Sdes		arc4random_buf(cp + 8 - padding, padding);
89257429Smarkm	}
893294332Sdes	if ((r = sshbuf_consume(state->outgoing_packet, 8 - padding)) != 0)
894294332Sdes		goto out;
89557429Smarkm
89657429Smarkm	/* Add check bytes. */
897294332Sdes	checksum = ssh_crc32(sshbuf_ptr(state->outgoing_packet),
898294332Sdes	    sshbuf_len(state->outgoing_packet));
899294332Sdes	POKE_U32(buf, checksum);
900294332Sdes	if ((r = sshbuf_put(state->outgoing_packet, buf, 4)) != 0)
901294332Sdes		goto out;
90257429Smarkm
90357429Smarkm#ifdef PACKET_DEBUG
90457429Smarkm	fprintf(stderr, "packet_send plain: ");
905294332Sdes	sshbuf_dump(state->outgoing_packet, stderr);
90657429Smarkm#endif
90757429Smarkm
90857429Smarkm	/* Append to output. */
909294332Sdes	POKE_U32(buf, len);
910294332Sdes	if ((r = sshbuf_put(state->output, buf, 4)) != 0)
911294332Sdes		goto out;
912294332Sdes	if ((r = sshbuf_reserve(state->output,
913294332Sdes	    sshbuf_len(state->outgoing_packet), &cp)) != 0)
914294332Sdes		goto out;
915323134Sdes	if ((r = cipher_crypt(state->send_context, 0, cp,
916294332Sdes	    sshbuf_ptr(state->outgoing_packet),
917294332Sdes	    sshbuf_len(state->outgoing_packet), 0, 0)) != 0)
918294332Sdes		goto out;
91957429Smarkm
92057429Smarkm#ifdef PACKET_DEBUG
92157429Smarkm	fprintf(stderr, "encrypted: ");
922294332Sdes	sshbuf_dump(state->output, stderr);
92357429Smarkm#endif
924294332Sdes	state->p_send.packets++;
925294332Sdes	state->p_send.bytes += len +
926294332Sdes	    sshbuf_len(state->outgoing_packet);
927294332Sdes	sshbuf_reset(state->outgoing_packet);
92857429Smarkm
92957429Smarkm	/*
930157016Sdes	 * Note that the packet is now only buffered in output.  It won't be
931294332Sdes	 * actually sent until ssh_packet_write_wait or ssh_packet_write_poll
932294332Sdes	 * is called.
93357429Smarkm	 */
934294332Sdes	r = 0;
935294332Sdes out:
936294332Sdes	return r;
93757429Smarkm}
93857429Smarkm
939294332Sdesint
940294332Sdesssh_set_newkeys(struct ssh *ssh, int mode)
94176259Sgreen{
942294332Sdes	struct session_state *state = ssh->state;
943294332Sdes	struct sshenc *enc;
944294332Sdes	struct sshmac *mac;
945294332Sdes	struct sshcomp *comp;
946323134Sdes	struct sshcipher_ctx **ccp;
947323134Sdes	struct packet_state *ps;
948124208Sdes	u_int64_t *max_blocks;
949323134Sdes	const char *wmsg, *dir;
950294328Sdes	int r, crypt_type;
95176259Sgreen
952113908Sdes	debug2("set_newkeys: mode %d", mode);
95376259Sgreen
95492555Sdes	if (mode == MODE_OUT) {
955323134Sdes		dir = "output";
956323134Sdes		ccp = &state->send_context;
957137015Sdes		crypt_type = CIPHER_ENCRYPT;
958323134Sdes		ps = &state->p_send;
959294332Sdes		max_blocks = &state->max_blocks_out;
96092555Sdes	} else {
961323134Sdes		dir = "input";
962323134Sdes		ccp = &state->receive_context;
963137015Sdes		crypt_type = CIPHER_DECRYPT;
964323134Sdes		ps = &state->p_read;
965294332Sdes		max_blocks = &state->max_blocks_in;
96692555Sdes	}
967294332Sdes	if (state->newkeys[mode] != NULL) {
968323134Sdes		debug("%s: rekeying after %llu %s blocks"
969323134Sdes		    " (%llu bytes total)", __func__,
970323134Sdes		    (unsigned long long)ps->blocks, dir,
971323134Sdes		    (unsigned long long)ps->bytes);
972323134Sdes		cipher_free(*ccp);
973323134Sdes		*ccp = NULL;
974294332Sdes		enc  = &state->newkeys[mode]->enc;
975294332Sdes		mac  = &state->newkeys[mode]->mac;
976294332Sdes		comp = &state->newkeys[mode]->comp;
977181111Sdes		mac_clear(mac);
978263712Sdes		explicit_bzero(enc->iv,  enc->iv_len);
979263712Sdes		explicit_bzero(enc->key, enc->key_len);
980263712Sdes		explicit_bzero(mac->key, mac->key_len);
981255767Sdes		free(enc->name);
982255767Sdes		free(enc->iv);
983255767Sdes		free(enc->key);
984255767Sdes		free(mac->name);
985255767Sdes		free(mac->key);
986255767Sdes		free(comp->name);
987294332Sdes		free(state->newkeys[mode]);
98876259Sgreen	}
989323134Sdes	/* note that both bytes and the seqnr are not reset */
990323134Sdes	ps->packets = ps->blocks = 0;
991294332Sdes	/* move newkeys from kex to state */
992294332Sdes	if ((state->newkeys[mode] = ssh->kex->newkeys[mode]) == NULL)
993294332Sdes		return SSH_ERR_INTERNAL_ERROR;
994294332Sdes	ssh->kex->newkeys[mode] = NULL;
995294332Sdes	enc  = &state->newkeys[mode]->enc;
996294332Sdes	mac  = &state->newkeys[mode]->mac;
997294332Sdes	comp = &state->newkeys[mode]->comp;
998294332Sdes	if (cipher_authlen(enc->cipher) == 0) {
999294332Sdes		if ((r = mac_init(mac)) != 0)
1000294332Sdes			return r;
1001294332Sdes	}
1002294332Sdes	mac->enabled = 1;
100376259Sgreen	DBG(debug("cipher_init_context: %d", mode));
1004323134Sdes	if ((r = cipher_init(ccp, enc->cipher, enc->key, enc->key_len,
1005294328Sdes	    enc->iv, enc->iv_len, crypt_type)) != 0)
1006294332Sdes		return r;
1007294332Sdes	if (!state->cipher_warning_done &&
1008323134Sdes	    (wmsg = cipher_warning_message(*ccp)) != NULL) {
1009294332Sdes		error("Warning: %s", wmsg);
1010294332Sdes		state->cipher_warning_done = 1;
1011294332Sdes	}
101298675Sdes	/* Deleting the keys does not gain extra security */
1013263712Sdes	/* explicit_bzero(enc->iv,  enc->block_size);
1014263712Sdes	   explicit_bzero(enc->key, enc->key_len);
1015263712Sdes	   explicit_bzero(mac->key, mac->key_len); */
1016149749Sdes	if ((comp->type == COMP_ZLIB ||
1017197679Sdes	    (comp->type == COMP_DELAYED &&
1018294332Sdes	     state->after_authentication)) && comp->enabled == 0) {
1019294332Sdes		if ((r = ssh_packet_init_compression(ssh)) < 0)
1020294332Sdes			return r;
1021294332Sdes		if (mode == MODE_OUT) {
1022294332Sdes			if ((r = start_compression_out(ssh, 6)) != 0)
1023294332Sdes				return r;
1024294332Sdes		} else {
1025294332Sdes			if ((r = start_compression_in(ssh)) != 0)
1026294332Sdes				return r;
1027294332Sdes		}
102876259Sgreen		comp->enabled = 1;
102976259Sgreen	}
1030124208Sdes	/*
1031124208Sdes	 * The 2^(blocksize*2) limit is too expensive for 3DES,
1032124208Sdes	 * blowfish, etc, so enforce a 1GB limit for small blocksizes.
1033124208Sdes	 */
1034124208Sdes	if (enc->block_size >= 16)
1035124208Sdes		*max_blocks = (u_int64_t)1 << (enc->block_size*2);
1036124208Sdes	else
1037124208Sdes		*max_blocks = ((u_int64_t)1 << 30) / enc->block_size;
1038294332Sdes	if (state->rekey_limit)
1039323134Sdes		*max_blocks = MINIMUM(*max_blocks,
1040294332Sdes		    state->rekey_limit / enc->block_size);
1041296633Sdes	debug("rekey after %llu blocks", (unsigned long long)*max_blocks);
1042294332Sdes	return 0;
104376259Sgreen}
104476259Sgreen
1045296633Sdes#define MAX_PACKETS	(1U<<31)
1046296633Sdesstatic int
1047296633Sdesssh_packet_need_rekeying(struct ssh *ssh, u_int outbound_packet_len)
1048296633Sdes{
1049296633Sdes	struct session_state *state = ssh->state;
1050296633Sdes	u_int32_t out_blocks;
1051296633Sdes
1052296633Sdes	/* XXX client can't cope with rekeying pre-auth */
1053296633Sdes	if (!state->after_authentication)
1054296633Sdes		return 0;
1055296633Sdes
1056296633Sdes	/* Haven't keyed yet or KEX in progress. */
1057296633Sdes	if (ssh->kex == NULL || ssh_packet_is_rekeying(ssh))
1058296633Sdes		return 0;
1059296633Sdes
1060296633Sdes	/* Peer can't rekey */
1061296633Sdes	if (ssh->compat & SSH_BUG_NOREKEY)
1062296633Sdes		return 0;
1063296633Sdes
1064296633Sdes	/*
1065296633Sdes	 * Permit one packet in or out per rekey - this allows us to
1066296633Sdes	 * make progress when rekey limits are very small.
1067296633Sdes	 */
1068296633Sdes	if (state->p_send.packets == 0 && state->p_read.packets == 0)
1069296633Sdes		return 0;
1070296633Sdes
1071296633Sdes	/* Time-based rekeying */
1072296633Sdes	if (state->rekey_interval != 0 &&
1073323136Sdes	    (int64_t)state->rekey_time + state->rekey_interval <= monotime())
1074296633Sdes		return 1;
1075296633Sdes
1076296633Sdes	/* Always rekey when MAX_PACKETS sent in either direction */
1077296633Sdes	if (state->p_send.packets > MAX_PACKETS ||
1078296633Sdes	    state->p_read.packets > MAX_PACKETS)
1079296633Sdes		return 1;
1080296633Sdes
1081296633Sdes	/* Rekey after (cipher-specific) maxiumum blocks */
1082323134Sdes	out_blocks = ROUNDUP(outbound_packet_len,
1083296633Sdes	    state->newkeys[MODE_OUT]->enc.block_size);
1084296633Sdes	return (state->max_blocks_out &&
1085296633Sdes	    (state->p_send.blocks + out_blocks > state->max_blocks_out)) ||
1086296633Sdes	    (state->max_blocks_in &&
1087296633Sdes	    (state->p_read.blocks > state->max_blocks_in));
1088296633Sdes}
1089296633Sdes
109057429Smarkm/*
1091149749Sdes * Delayed compression for SSH2 is enabled after authentication:
1092162852Sdes * This happens on the server side after a SSH2_MSG_USERAUTH_SUCCESS is sent,
1093149749Sdes * and on the client side after a SSH2_MSG_USERAUTH_SUCCESS is received.
1094149749Sdes */
1095294332Sdesstatic int
1096294332Sdesssh_packet_enable_delayed_compress(struct ssh *ssh)
1097149749Sdes{
1098294332Sdes	struct session_state *state = ssh->state;
1099294332Sdes	struct sshcomp *comp = NULL;
1100294332Sdes	int r, mode;
1101149749Sdes
1102149749Sdes	/*
1103149749Sdes	 * Remember that we are past the authentication step, so rekeying
1104149749Sdes	 * with COMP_DELAYED will turn on compression immediately.
1105149749Sdes	 */
1106294332Sdes	state->after_authentication = 1;
1107149749Sdes	for (mode = 0; mode < MODE_MAX; mode++) {
1108162852Sdes		/* protocol error: USERAUTH_SUCCESS received before NEWKEYS */
1109294332Sdes		if (state->newkeys[mode] == NULL)
1110162852Sdes			continue;
1111294332Sdes		comp = &state->newkeys[mode]->comp;
1112149749Sdes		if (comp && !comp->enabled && comp->type == COMP_DELAYED) {
1113294332Sdes			if ((r = ssh_packet_init_compression(ssh)) != 0)
1114294332Sdes				return r;
1115294332Sdes			if (mode == MODE_OUT) {
1116294332Sdes				if ((r = start_compression_out(ssh, 6)) != 0)
1117294332Sdes					return r;
1118294332Sdes			} else {
1119294332Sdes				if ((r = start_compression_in(ssh)) != 0)
1120294332Sdes					return r;
1121294332Sdes			}
1122149749Sdes			comp->enabled = 1;
1123149749Sdes		}
1124149749Sdes	}
1125294332Sdes	return 0;
1126149749Sdes}
1127149749Sdes
1128296633Sdes/* Used to mute debug logging for noisy packet types */
1129323134Sdesint
1130296633Sdesssh_packet_log_type(u_char type)
1131296633Sdes{
1132296633Sdes	switch (type) {
1133296633Sdes	case SSH2_MSG_CHANNEL_DATA:
1134296633Sdes	case SSH2_MSG_CHANNEL_EXTENDED_DATA:
1135296633Sdes	case SSH2_MSG_CHANNEL_WINDOW_ADJUST:
1136296633Sdes		return 0;
1137296633Sdes	default:
1138296633Sdes		return 1;
1139296633Sdes	}
1140296633Sdes}
1141296633Sdes
1142149749Sdes/*
114360573Skris * Finalize packet in SSH2 format (compress, mac, encrypt, enqueue)
114460573Skris */
1145294332Sdesint
1146294332Sdesssh_packet_send2_wrapped(struct ssh *ssh)
114760573Skris{
1148294332Sdes	struct session_state *state = ssh->state;
1149294332Sdes	u_char type, *cp, macbuf[SSH_DIGEST_MAX_LENGTH];
1150323129Sdes	u_char tmp, padlen, pad = 0;
1151294332Sdes	u_int authlen = 0, aadlen = 0;
1152294332Sdes	u_int len;
1153294332Sdes	struct sshenc *enc   = NULL;
1154294332Sdes	struct sshmac *mac   = NULL;
1155294332Sdes	struct sshcomp *comp = NULL;
1156294332Sdes	int r, block_size;
115760573Skris
1158294332Sdes	if (state->newkeys[MODE_OUT] != NULL) {
1159294332Sdes		enc  = &state->newkeys[MODE_OUT]->enc;
1160294332Sdes		mac  = &state->newkeys[MODE_OUT]->mac;
1161294332Sdes		comp = &state->newkeys[MODE_OUT]->comp;
1162248619Sdes		/* disable mac for authenticated encryption */
1163248619Sdes		if ((authlen = cipher_authlen(enc->cipher)) != 0)
1164248619Sdes			mac = NULL;
116560573Skris	}
116692555Sdes	block_size = enc ? enc->block_size : 8;
1167248619Sdes	aadlen = (mac && mac->enabled && mac->etm) || authlen ? 4 : 0;
116860573Skris
1169294332Sdes	type = (sshbuf_ptr(state->outgoing_packet))[5];
1170296633Sdes	if (ssh_packet_log_type(type))
1171296633Sdes		debug3("send packet: type %u", type);
117260573Skris#ifdef PACKET_DEBUG
117360573Skris	fprintf(stderr, "plain:     ");
1174294332Sdes	sshbuf_dump(state->outgoing_packet, stderr);
117560573Skris#endif
117660573Skris
117760573Skris	if (comp && comp->enabled) {
1178294332Sdes		len = sshbuf_len(state->outgoing_packet);
117960573Skris		/* skip header, compress only payload */
1180294332Sdes		if ((r = sshbuf_consume(state->outgoing_packet, 5)) != 0)
1181294332Sdes			goto out;
1182294332Sdes		sshbuf_reset(state->compression_buffer);
1183294332Sdes		if ((r = compress_buffer(ssh, state->outgoing_packet,
1184294332Sdes		    state->compression_buffer)) != 0)
1185294332Sdes			goto out;
1186294332Sdes		sshbuf_reset(state->outgoing_packet);
1187294332Sdes		if ((r = sshbuf_put(state->outgoing_packet,
1188294332Sdes		    "\0\0\0\0\0", 5)) != 0 ||
1189294332Sdes		    (r = sshbuf_putb(state->outgoing_packet,
1190294332Sdes		    state->compression_buffer)) != 0)
1191294332Sdes			goto out;
1192294332Sdes		DBG(debug("compression: raw %d compressed %zd", len,
1193294332Sdes		    sshbuf_len(state->outgoing_packet)));
119460573Skris	}
119560573Skris
119660573Skris	/* sizeof (packet_len + pad_len + payload) */
1197294332Sdes	len = sshbuf_len(state->outgoing_packet);
119860573Skris
119960573Skris	/*
120060573Skris	 * calc size of padding, alloc space, get random data,
120160573Skris	 * minimum padding is 4 bytes
120260573Skris	 */
1203248619Sdes	len -= aadlen; /* packet length is not encrypted for EtM modes */
120460573Skris	padlen = block_size - (len % block_size);
120560573Skris	if (padlen < 4)
120660573Skris		padlen += block_size;
1207294332Sdes	if (state->extra_pad) {
1208323129Sdes		tmp = state->extra_pad;
1209294332Sdes		state->extra_pad =
1210323134Sdes		    ROUNDUP(state->extra_pad, block_size);
1211323129Sdes		/* check if roundup overflowed */
1212323129Sdes		if (state->extra_pad < tmp)
1213323129Sdes			return SSH_ERR_INVALID_ARGUMENT;
1214323129Sdes		tmp = (len + padlen) % state->extra_pad;
1215323129Sdes		/* Check whether pad calculation below will underflow */
1216323129Sdes		if (tmp > state->extra_pad)
1217323129Sdes			return SSH_ERR_INVALID_ARGUMENT;
1218323129Sdes		pad = state->extra_pad - tmp;
1219294328Sdes		DBG(debug3("%s: adding %d (len %d padlen %d extra_pad %d)",
1220294332Sdes		    __func__, pad, len, padlen, state->extra_pad));
1221323129Sdes		tmp = padlen;
122292555Sdes		padlen += pad;
1223323129Sdes		/* Check whether padlen calculation overflowed */
1224323129Sdes		if (padlen < tmp)
1225323129Sdes			return SSH_ERR_INVALID_ARGUMENT; /* overflow */
1226294332Sdes		state->extra_pad = 0;
122792555Sdes	}
1228294332Sdes	if ((r = sshbuf_reserve(state->outgoing_packet, padlen, &cp)) != 0)
1229294332Sdes		goto out;
1230323134Sdes	if (enc && !cipher_ctx_is_plaintext(state->send_context)) {
123160573Skris		/* random padding */
1232294332Sdes		arc4random_buf(cp, padlen);
123360573Skris	} else {
123460573Skris		/* clear padding */
1235263712Sdes		explicit_bzero(cp, padlen);
123660573Skris	}
1237248619Sdes	/* sizeof (packet_len + pad_len + payload + padding) */
1238294332Sdes	len = sshbuf_len(state->outgoing_packet);
1239294332Sdes	cp = sshbuf_mutable_ptr(state->outgoing_packet);
1240294332Sdes	if (cp == NULL) {
1241294332Sdes		r = SSH_ERR_INTERNAL_ERROR;
1242294332Sdes		goto out;
1243294332Sdes	}
124460573Skris	/* packet_length includes payload, padding and padding length field */
1245294332Sdes	POKE_U32(cp, len - 4);
124692555Sdes	cp[4] = padlen;
1247248619Sdes	DBG(debug("send: len %d (includes padlen %d, aadlen %d)",
1248248619Sdes	    len, padlen, aadlen));
124960573Skris
125060573Skris	/* compute MAC over seqnr and packet(length fields, payload, padding) */
1251248619Sdes	if (mac && mac->enabled && !mac->etm) {
1252294332Sdes		if ((r = mac_compute(mac, state->p_send.seqnr,
1253294332Sdes		    sshbuf_ptr(state->outgoing_packet), len,
1254294332Sdes		    macbuf, sizeof(macbuf))) != 0)
1255294332Sdes			goto out;
1256294332Sdes		DBG(debug("done calc MAC out #%d", state->p_send.seqnr));
125760573Skris	}
125860573Skris	/* encrypt packet and append to output buffer. */
1259294332Sdes	if ((r = sshbuf_reserve(state->output,
1260294332Sdes	    sshbuf_len(state->outgoing_packet) + authlen, &cp)) != 0)
1261294332Sdes		goto out;
1262323134Sdes	if ((r = cipher_crypt(state->send_context, state->p_send.seqnr, cp,
1263294332Sdes	    sshbuf_ptr(state->outgoing_packet),
1264294332Sdes	    len - aadlen, aadlen, authlen)) != 0)
1265294332Sdes		goto out;
126660573Skris	/* append unencrypted MAC */
1267248619Sdes	if (mac && mac->enabled) {
1268248619Sdes		if (mac->etm) {
1269248619Sdes			/* EtM: compute mac over aadlen + cipher text */
1270294332Sdes			if ((r = mac_compute(mac, state->p_send.seqnr,
1271294332Sdes			    cp, len, macbuf, sizeof(macbuf))) != 0)
1272294332Sdes				goto out;
1273248619Sdes			DBG(debug("done calc MAC(EtM) out #%d",
1274294332Sdes			    state->p_send.seqnr));
1275248619Sdes		}
1276294332Sdes		if ((r = sshbuf_put(state->output, macbuf, mac->mac_len)) != 0)
1277294332Sdes			goto out;
1278248619Sdes	}
127960573Skris#ifdef PACKET_DEBUG
128060573Skris	fprintf(stderr, "encrypted: ");
1281294332Sdes	sshbuf_dump(state->output, stderr);
128260573Skris#endif
128360573Skris	/* increment sequence number for outgoing packets */
1284294332Sdes	if (++state->p_send.seqnr == 0)
1285124208Sdes		logit("outgoing seqnr wraps around");
1286294332Sdes	if (++state->p_send.packets == 0)
1287294332Sdes		if (!(ssh->compat & SSH_BUG_NOREKEY))
1288294332Sdes			return SSH_ERR_NEED_REKEY;
1289294332Sdes	state->p_send.blocks += len / block_size;
1290294332Sdes	state->p_send.bytes += len;
1291294332Sdes	sshbuf_reset(state->outgoing_packet);
129260573Skris
129376259Sgreen	if (type == SSH2_MSG_NEWKEYS)
1294294332Sdes		r = ssh_set_newkeys(ssh, MODE_OUT);
1295294332Sdes	else if (type == SSH2_MSG_USERAUTH_SUCCESS && state->server_side)
1296294332Sdes		r = ssh_packet_enable_delayed_compress(ssh);
1297294332Sdes	else
1298294332Sdes		r = 0;
1299294332Sdes out:
1300294332Sdes	return r;
130160573Skris}
130260573Skris
1303296633Sdes/* returns non-zero if the specified packet type is usec by KEX */
1304296633Sdesstatic int
1305296633Sdesssh_packet_type_is_kex(u_char type)
1306296633Sdes{
1307296633Sdes	return
1308296633Sdes	    type >= SSH2_MSG_TRANSPORT_MIN &&
1309296633Sdes	    type <= SSH2_MSG_TRANSPORT_MAX &&
1310296633Sdes	    type != SSH2_MSG_SERVICE_REQUEST &&
1311296633Sdes	    type != SSH2_MSG_SERVICE_ACCEPT &&
1312296633Sdes	    type != SSH2_MSG_EXT_INFO;
1313296633Sdes}
1314296633Sdes
1315294332Sdesint
1316294332Sdesssh_packet_send2(struct ssh *ssh)
1317124208Sdes{
1318294332Sdes	struct session_state *state = ssh->state;
1319124208Sdes	struct packet *p;
1320294332Sdes	u_char type;
1321296633Sdes	int r, need_rekey;
1322124208Sdes
1323296633Sdes	if (sshbuf_len(state->outgoing_packet) < 6)
1324296633Sdes		return SSH_ERR_INTERNAL_ERROR;
1325294332Sdes	type = sshbuf_ptr(state->outgoing_packet)[5];
1326296633Sdes	need_rekey = !ssh_packet_type_is_kex(type) &&
1327296633Sdes	    ssh_packet_need_rekeying(ssh, sshbuf_len(state->outgoing_packet));
1328124208Sdes
1329296633Sdes	/*
1330296633Sdes	 * During rekeying we can only send key exchange messages.
1331296633Sdes	 * Queue everything else.
1332296633Sdes	 */
1333296633Sdes	if ((need_rekey || state->rekeying) && !ssh_packet_type_is_kex(type)) {
1334296633Sdes		if (need_rekey)
1335296633Sdes			debug3("%s: rekex triggered", __func__);
1336296633Sdes		debug("enqueue packet: %u", type);
1337296633Sdes		p = calloc(1, sizeof(*p));
1338296633Sdes		if (p == NULL)
1339296633Sdes			return SSH_ERR_ALLOC_FAIL;
1340296633Sdes		p->type = type;
1341296633Sdes		p->payload = state->outgoing_packet;
1342296633Sdes		TAILQ_INSERT_TAIL(&state->outgoing, p, next);
1343296633Sdes		state->outgoing_packet = sshbuf_new();
1344296633Sdes		if (state->outgoing_packet == NULL)
1345296633Sdes			return SSH_ERR_ALLOC_FAIL;
1346296633Sdes		if (need_rekey) {
1347296633Sdes			/*
1348296633Sdes			 * This packet triggered a rekey, so send the
1349296633Sdes			 * KEXINIT now.
1350296633Sdes			 * NB. reenters this function via kex_start_rekex().
1351296633Sdes			 */
1352296633Sdes			return kex_start_rekex(ssh);
1353124208Sdes		}
1354296633Sdes		return 0;
1355124208Sdes	}
1356124208Sdes
1357124208Sdes	/* rekeying starts with sending KEXINIT */
1358124208Sdes	if (type == SSH2_MSG_KEXINIT)
1359294332Sdes		state->rekeying = 1;
1360124208Sdes
1361294332Sdes	if ((r = ssh_packet_send2_wrapped(ssh)) != 0)
1362294332Sdes		return r;
1363124208Sdes
1364124208Sdes	/* after a NEWKEYS message we can send the complete queue */
1365124208Sdes	if (type == SSH2_MSG_NEWKEYS) {
1366294332Sdes		state->rekeying = 0;
1367294332Sdes		state->rekey_time = monotime();
1368294332Sdes		while ((p = TAILQ_FIRST(&state->outgoing))) {
1369124208Sdes			type = p->type;
1370296633Sdes			/*
1371296633Sdes			 * If this packet triggers a rekex, then skip the
1372296633Sdes			 * remaining packets in the queue for now.
1373296633Sdes			 * NB. re-enters this function via kex_start_rekex.
1374296633Sdes			 */
1375296633Sdes			if (ssh_packet_need_rekeying(ssh,
1376296633Sdes			    sshbuf_len(p->payload))) {
1377296633Sdes				debug3("%s: queued packet triggered rekex",
1378296633Sdes				    __func__);
1379296633Sdes				return kex_start_rekex(ssh);
1380296633Sdes			}
1381124208Sdes			debug("dequeue packet: %u", type);
1382294332Sdes			sshbuf_free(state->outgoing_packet);
1383294332Sdes			state->outgoing_packet = p->payload;
1384294332Sdes			TAILQ_REMOVE(&state->outgoing, p, next);
1385296633Sdes			memset(p, 0, sizeof(*p));
1386255767Sdes			free(p);
1387294332Sdes			if ((r = ssh_packet_send2_wrapped(ssh)) != 0)
1388294332Sdes				return r;
1389124208Sdes		}
1390124208Sdes	}
1391294332Sdes	return 0;
1392124208Sdes}
1393124208Sdes
139460573Skris/*
139557429Smarkm * Waits until a packet has been received, and returns its type.  Note that
139657429Smarkm * no other data is processed until this returns, so this function should not
139757429Smarkm * be used during the interactive session.
139857429Smarkm */
139957429Smarkm
140057429Smarkmint
1401294332Sdesssh_packet_read_seqnr(struct ssh *ssh, u_char *typep, u_int32_t *seqnr_p)
140257429Smarkm{
1403294332Sdes	struct session_state *state = ssh->state;
1404296633Sdes	int len, r, ms_remain;
140576259Sgreen	fd_set *setp;
140657429Smarkm	char buf[8192];
1407181111Sdes	struct timeval timeout, start, *timeoutp = NULL;
1408181111Sdes
140960573Skris	DBG(debug("packet_read()"));
141057429Smarkm
1411294496Sdes	setp = calloc(howmany(state->connection_in + 1,
1412197679Sdes	    NFDBITS), sizeof(fd_mask));
1413294332Sdes	if (setp == NULL)
1414294332Sdes		return SSH_ERR_ALLOC_FAIL;
141576259Sgreen
1416294332Sdes	/*
1417294332Sdes	 * Since we are blocking, ensure that all written packets have
1418294332Sdes	 * been sent.
1419294332Sdes	 */
1420294332Sdes	if ((r = ssh_packet_write_wait(ssh)) != 0)
1421294336Sdes		goto out;
142257429Smarkm
142357429Smarkm	/* Stay in the loop until we have received a complete packet. */
142457429Smarkm	for (;;) {
142557429Smarkm		/* Try to read a packet from the buffer. */
1426294332Sdes		r = ssh_packet_read_poll_seqnr(ssh, typep, seqnr_p);
1427294332Sdes		if (r != 0)
1428294332Sdes			break;
142992555Sdes		if (!compat20 && (
1430294332Sdes		    *typep == SSH_SMSG_SUCCESS
1431294332Sdes		    || *typep == SSH_SMSG_FAILURE
1432294332Sdes		    || *typep == SSH_CMSG_EOF
1433294332Sdes		    || *typep == SSH_CMSG_EXIT_CONFIRMATION))
1434294332Sdes			if ((r = sshpkt_get_end(ssh)) != 0)
1435294332Sdes				break;
143657429Smarkm		/* If we got a packet, return it. */
1437294332Sdes		if (*typep != SSH_MSG_NONE)
1438294332Sdes			break;
143957429Smarkm		/*
144057429Smarkm		 * Otherwise, wait for some data to arrive, add it to the
144157429Smarkm		 * buffer, and try again.
144257429Smarkm		 */
1443294332Sdes		memset(setp, 0, howmany(state->connection_in + 1,
1444197679Sdes		    NFDBITS) * sizeof(fd_mask));
1445294332Sdes		FD_SET(state->connection_in, setp);
144657429Smarkm
1447294332Sdes		if (state->packet_timeout_ms > 0) {
1448294332Sdes			ms_remain = state->packet_timeout_ms;
1449181111Sdes			timeoutp = &timeout;
1450181111Sdes		}
145157429Smarkm		/* Wait for some data to arrive. */
1452181111Sdes		for (;;) {
1453294332Sdes			if (state->packet_timeout_ms != -1) {
1454181111Sdes				ms_to_timeval(&timeout, ms_remain);
1455181111Sdes				gettimeofday(&start, NULL);
1456181111Sdes			}
1457294332Sdes			if ((r = select(state->connection_in + 1, setp,
1458197679Sdes			    NULL, NULL, timeoutp)) >= 0)
1459181111Sdes				break;
1460197679Sdes			if (errno != EAGAIN && errno != EINTR &&
1461181111Sdes			    errno != EWOULDBLOCK)
1462181111Sdes				break;
1463294332Sdes			if (state->packet_timeout_ms == -1)
1464181111Sdes				continue;
1465181111Sdes			ms_subtract_diff(&start, &ms_remain);
1466181111Sdes			if (ms_remain <= 0) {
1467294332Sdes				r = 0;
1468181111Sdes				break;
1469181111Sdes			}
1470181111Sdes		}
1471323136Sdes		if (r == 0) {
1472323136Sdes			r = SSH_ERR_CONN_TIMEOUT;
1473323136Sdes			goto out;
1474323136Sdes		}
147557429Smarkm		/* Read data from the socket. */
1476296633Sdes		len = read(state->connection_in, buf, sizeof(buf));
1477294336Sdes		if (len == 0) {
1478294336Sdes			r = SSH_ERR_CONN_CLOSED;
1479294336Sdes			goto out;
1480294336Sdes		}
1481294336Sdes		if (len < 0) {
1482294336Sdes			r = SSH_ERR_SYSTEM_ERROR;
1483294336Sdes			goto out;
1484294336Sdes		}
1485294332Sdes
148657429Smarkm		/* Append it to the buffer. */
1487294332Sdes		if ((r = ssh_packet_process_incoming(ssh, buf, len)) != 0)
1488294336Sdes			goto out;
148957429Smarkm	}
1490294336Sdes out:
1491294332Sdes	free(setp);
1492294332Sdes	return r;
149357429Smarkm}
149457429Smarkm
149592555Sdesint
1496294332Sdesssh_packet_read(struct ssh *ssh)
149792555Sdes{
1498294332Sdes	u_char type;
1499294332Sdes	int r;
1500294332Sdes
1501294332Sdes	if ((r = ssh_packet_read_seqnr(ssh, &type, NULL)) != 0)
1502294332Sdes		fatal("%s: %s", __func__, ssh_err(r));
1503294332Sdes	return type;
150492555Sdes}
150592555Sdes
150657429Smarkm/*
150757429Smarkm * Waits until a packet has been received, verifies that its type matches
150857429Smarkm * that given, and gives a fatal error and exits if there is a mismatch.
150957429Smarkm */
151057429Smarkm
1511294332Sdesint
1512294332Sdesssh_packet_read_expect(struct ssh *ssh, u_int expected_type)
151357429Smarkm{
1514294332Sdes	int r;
1515294332Sdes	u_char type;
151657429Smarkm
1517294332Sdes	if ((r = ssh_packet_read_seqnr(ssh, &type, NULL)) != 0)
1518294332Sdes		return r;
1519294332Sdes	if (type != expected_type) {
1520294332Sdes		if ((r = sshpkt_disconnect(ssh,
1521294332Sdes		    "Protocol error: expected packet type %d, got %d",
1522294332Sdes		    expected_type, type)) != 0)
1523294332Sdes			return r;
1524294332Sdes		return SSH_ERR_PROTOCOL_ERROR;
1525294332Sdes	}
1526294332Sdes	return 0;
152757429Smarkm}
152857429Smarkm
152957429Smarkm/* Checks if a full packet is available in the data received so far via
153057429Smarkm * packet_process_incoming.  If so, reads the packet; otherwise returns
153157429Smarkm * SSH_MSG_NONE.  This does not wait for data from the connection.
153257429Smarkm *
153357429Smarkm * SSH_MSG_DISCONNECT is handled specially here.  Also,
153457429Smarkm * SSH_MSG_IGNORE messages are skipped by this function and are never returned
153557429Smarkm * to higher levels.
153657429Smarkm */
153757429Smarkm
1538294332Sdesint
1539294332Sdesssh_packet_read_poll1(struct ssh *ssh, u_char *typep)
154057429Smarkm{
1541294332Sdes	struct session_state *state = ssh->state;
154276259Sgreen	u_int len, padded_len;
1543294332Sdes	const char *emsg;
1544294332Sdes	const u_char *cp;
1545294332Sdes	u_char *p;
154676259Sgreen	u_int checksum, stored_checksum;
1547294332Sdes	int r;
154857429Smarkm
1549294332Sdes	*typep = SSH_MSG_NONE;
1550294332Sdes
155157429Smarkm	/* Check if input size is less than minimum packet size. */
1552294332Sdes	if (sshbuf_len(state->input) < 4 + 8)
1553294332Sdes		return 0;
155457429Smarkm	/* Get length of incoming packet. */
1555294332Sdes	len = PEEK_U32(sshbuf_ptr(state->input));
1556294332Sdes	if (len < 1 + 2 + 2 || len > 256 * 1024) {
1557294332Sdes		if ((r = sshpkt_disconnect(ssh, "Bad packet length %u",
1558294332Sdes		    len)) != 0)
1559294332Sdes			return r;
1560294332Sdes		return SSH_ERR_CONN_CORRUPT;
1561294332Sdes	}
156257429Smarkm	padded_len = (len + 8) & ~7;
156357429Smarkm
156457429Smarkm	/* Check if the packet has been entirely received. */
1565294332Sdes	if (sshbuf_len(state->input) < 4 + padded_len)
1566294332Sdes		return 0;
156757429Smarkm
156857429Smarkm	/* The entire packet is in buffer. */
156957429Smarkm
157057429Smarkm	/* Consume packet length. */
1571294332Sdes	if ((r = sshbuf_consume(state->input, 4)) != 0)
1572294332Sdes		goto out;
157357429Smarkm
157492555Sdes	/*
157592555Sdes	 * Cryptographic attack detector for ssh
157692555Sdes	 * (C)1998 CORE-SDI, Buenos Aires Argentina
157792555Sdes	 * Ariel Futoransky(futo@core-sdi.com)
157892555Sdes	 */
1579323134Sdes	if (!cipher_ctx_is_plaintext(state->receive_context)) {
1580294332Sdes		emsg = NULL;
1581294332Sdes		switch (detect_attack(&state->deattack,
1582294332Sdes		    sshbuf_ptr(state->input), padded_len)) {
1583294332Sdes		case DEATTACK_OK:
1584294332Sdes			break;
1585162852Sdes		case DEATTACK_DETECTED:
1586294332Sdes			emsg = "crc32 compensation attack detected";
1587294332Sdes			break;
1588162852Sdes		case DEATTACK_DOS_DETECTED:
1589294332Sdes			emsg = "deattack denial of service detected";
1590294332Sdes			break;
1591294332Sdes		default:
1592294332Sdes			emsg = "deattack error";
1593294332Sdes			break;
1594162852Sdes		}
1595294332Sdes		if (emsg != NULL) {
1596294332Sdes			error("%s", emsg);
1597294332Sdes			if ((r = sshpkt_disconnect(ssh, "%s", emsg)) != 0 ||
1598294332Sdes			    (r = ssh_packet_write_wait(ssh)) != 0)
1599294332Sdes					return r;
1600294332Sdes			return SSH_ERR_CONN_CORRUPT;
1601294332Sdes		}
1602162852Sdes	}
160392555Sdes
160492555Sdes	/* Decrypt data to incoming_packet. */
1605294332Sdes	sshbuf_reset(state->incoming_packet);
1606294332Sdes	if ((r = sshbuf_reserve(state->incoming_packet, padded_len, &p)) != 0)
1607294332Sdes		goto out;
1608323134Sdes	if ((r = cipher_crypt(state->receive_context, 0, p,
1609294332Sdes	    sshbuf_ptr(state->input), padded_len, 0, 0)) != 0)
1610294332Sdes		goto out;
161192555Sdes
1612294332Sdes	if ((r = sshbuf_consume(state->input, padded_len)) != 0)
1613294332Sdes		goto out;
161457429Smarkm
161557429Smarkm#ifdef PACKET_DEBUG
161657429Smarkm	fprintf(stderr, "read_poll plain: ");
1617294332Sdes	sshbuf_dump(state->incoming_packet, stderr);
161857429Smarkm#endif
161957429Smarkm
162057429Smarkm	/* Compute packet checksum. */
1621294332Sdes	checksum = ssh_crc32(sshbuf_ptr(state->incoming_packet),
1622294332Sdes	    sshbuf_len(state->incoming_packet) - 4);
162357429Smarkm
162457429Smarkm	/* Skip padding. */
1625294332Sdes	if ((r = sshbuf_consume(state->incoming_packet, 8 - len % 8)) != 0)
1626294332Sdes		goto out;
162757429Smarkm
162857429Smarkm	/* Test check bytes. */
1629294332Sdes	if (len != sshbuf_len(state->incoming_packet)) {
1630294332Sdes		error("%s: len %d != sshbuf_len %zd", __func__,
1631294332Sdes		    len, sshbuf_len(state->incoming_packet));
1632294332Sdes		if ((r = sshpkt_disconnect(ssh, "invalid packet length")) != 0 ||
1633294332Sdes		    (r = ssh_packet_write_wait(ssh)) != 0)
1634294332Sdes			return r;
1635294332Sdes		return SSH_ERR_CONN_CORRUPT;
1636294332Sdes	}
163757429Smarkm
1638294332Sdes	cp = sshbuf_ptr(state->incoming_packet) + len - 4;
1639294332Sdes	stored_checksum = PEEK_U32(cp);
1640294332Sdes	if (checksum != stored_checksum) {
1641294332Sdes		error("Corrupted check bytes on input");
1642294332Sdes		if ((r = sshpkt_disconnect(ssh, "connection corrupted")) != 0 ||
1643294332Sdes		    (r = ssh_packet_write_wait(ssh)) != 0)
1644294332Sdes			return r;
1645294332Sdes		return SSH_ERR_CONN_CORRUPT;
1646294332Sdes	}
1647294332Sdes	if ((r = sshbuf_consume_end(state->incoming_packet, 4)) < 0)
1648294332Sdes		goto out;
164957429Smarkm
1650294332Sdes	if (state->packet_compression) {
1651294332Sdes		sshbuf_reset(state->compression_buffer);
1652294332Sdes		if ((r = uncompress_buffer(ssh, state->incoming_packet,
1653294332Sdes		    state->compression_buffer)) != 0)
1654294332Sdes			goto out;
1655294332Sdes		sshbuf_reset(state->incoming_packet);
1656294332Sdes		if ((r = sshbuf_putb(state->incoming_packet,
1657294332Sdes		    state->compression_buffer)) != 0)
1658294332Sdes			goto out;
165957429Smarkm	}
1660294332Sdes	state->p_read.packets++;
1661294332Sdes	state->p_read.bytes += padded_len + 4;
1662294332Sdes	if ((r = sshbuf_get_u8(state->incoming_packet, typep)) != 0)
1663294332Sdes		goto out;
1664294332Sdes	if (*typep < SSH_MSG_MIN || *typep > SSH_MSG_MAX) {
1665294332Sdes		error("Invalid ssh1 packet type: %d", *typep);
1666294332Sdes		if ((r = sshpkt_disconnect(ssh, "invalid packet type")) != 0 ||
1667294332Sdes		    (r = ssh_packet_write_wait(ssh)) != 0)
1668294332Sdes			return r;
1669294332Sdes		return SSH_ERR_PROTOCOL_ERROR;
1670294332Sdes	}
1671294332Sdes	r = 0;
1672294332Sdes out:
1673294332Sdes	return r;
167460573Skris}
167557429Smarkm
1676323134Sdesstatic int
1677323134Sdesssh_packet_read_poll2_mux(struct ssh *ssh, u_char *typep, u_int32_t *seqnr_p)
1678323134Sdes{
1679323134Sdes	struct session_state *state = ssh->state;
1680323134Sdes	const u_char *cp;
1681323134Sdes	size_t need;
1682323134Sdes	int r;
1683323134Sdes
1684323134Sdes	if (ssh->kex)
1685323134Sdes		return SSH_ERR_INTERNAL_ERROR;
1686323134Sdes	*typep = SSH_MSG_NONE;
1687323134Sdes	cp = sshbuf_ptr(state->input);
1688323134Sdes	if (state->packlen == 0) {
1689323134Sdes		if (sshbuf_len(state->input) < 4 + 1)
1690323134Sdes			return 0; /* packet is incomplete */
1691323134Sdes		state->packlen = PEEK_U32(cp);
1692323134Sdes		if (state->packlen < 4 + 1 ||
1693323134Sdes		    state->packlen > PACKET_MAX_SIZE)
1694323134Sdes			return SSH_ERR_MESSAGE_INCOMPLETE;
1695323134Sdes	}
1696323134Sdes	need = state->packlen + 4;
1697323134Sdes	if (sshbuf_len(state->input) < need)
1698323134Sdes		return 0; /* packet is incomplete */
1699323134Sdes	sshbuf_reset(state->incoming_packet);
1700323134Sdes	if ((r = sshbuf_put(state->incoming_packet, cp + 4,
1701323134Sdes	    state->packlen)) != 0 ||
1702323134Sdes	    (r = sshbuf_consume(state->input, need)) != 0 ||
1703323134Sdes	    (r = sshbuf_get_u8(state->incoming_packet, NULL)) != 0 ||
1704323134Sdes	    (r = sshbuf_get_u8(state->incoming_packet, typep)) != 0)
1705323134Sdes		return r;
1706323134Sdes	if (ssh_packet_log_type(*typep))
1707323134Sdes		debug3("%s: type %u", __func__, *typep);
1708323134Sdes	/* sshbuf_dump(state->incoming_packet, stderr); */
1709323134Sdes	/* reset for next packet */
1710323134Sdes	state->packlen = 0;
1711323134Sdes	return r;
1712323134Sdes}
1713323134Sdes
1714294332Sdesint
1715294332Sdesssh_packet_read_poll2(struct ssh *ssh, u_char *typep, u_int32_t *seqnr_p)
171660573Skris{
1717294332Sdes	struct session_state *state = ssh->state;
171876259Sgreen	u_int padlen, need;
1719323129Sdes	u_char *cp;
1720294332Sdes	u_int maclen, aadlen = 0, authlen = 0, block_size;
1721294332Sdes	struct sshenc *enc   = NULL;
1722294332Sdes	struct sshmac *mac   = NULL;
1723294332Sdes	struct sshcomp *comp = NULL;
1724294332Sdes	int r;
172557429Smarkm
1726323134Sdes	if (state->mux)
1727323134Sdes		return ssh_packet_read_poll2_mux(ssh, typep, seqnr_p);
1728323134Sdes
1729294332Sdes	*typep = SSH_MSG_NONE;
1730192595Sdes
1731294332Sdes	if (state->packet_discard)
1732294332Sdes		return 0;
1733294332Sdes
1734294332Sdes	if (state->newkeys[MODE_IN] != NULL) {
1735294332Sdes		enc  = &state->newkeys[MODE_IN]->enc;
1736294332Sdes		mac  = &state->newkeys[MODE_IN]->mac;
1737294332Sdes		comp = &state->newkeys[MODE_IN]->comp;
1738248619Sdes		/* disable mac for authenticated encryption */
1739248619Sdes		if ((authlen = cipher_authlen(enc->cipher)) != 0)
1740248619Sdes			mac = NULL;
174157429Smarkm	}
174260573Skris	maclen = mac && mac->enabled ? mac->mac_len : 0;
174392555Sdes	block_size = enc ? enc->block_size : 8;
1744248619Sdes	aadlen = (mac && mac->enabled && mac->etm) || authlen ? 4 : 0;
174560573Skris
1746294332Sdes	if (aadlen && state->packlen == 0) {
1747323134Sdes		if (cipher_get_length(state->receive_context,
1748294332Sdes		    &state->packlen, state->p_read.seqnr,
1749294332Sdes		    sshbuf_ptr(state->input), sshbuf_len(state->input)) != 0)
1750294332Sdes			return 0;
1751294332Sdes		if (state->packlen < 1 + 4 ||
1752294332Sdes		    state->packlen > PACKET_MAX_SIZE) {
1753248619Sdes#ifdef PACKET_DEBUG
1754294332Sdes			sshbuf_dump(state->input, stderr);
1755248619Sdes#endif
1756294332Sdes			logit("Bad packet length %u.", state->packlen);
1757294332Sdes			if ((r = sshpkt_disconnect(ssh, "Packet corrupt")) != 0)
1758294332Sdes				return r;
1759294496Sdes			return SSH_ERR_CONN_CORRUPT;
1760248619Sdes		}
1761294332Sdes		sshbuf_reset(state->incoming_packet);
1762294332Sdes	} else if (state->packlen == 0) {
176360573Skris		/*
176460573Skris		 * check if input size is less than the cipher block size,
176560573Skris		 * decrypt first block and extract length of incoming packet
176660573Skris		 */
1767294332Sdes		if (sshbuf_len(state->input) < block_size)
1768294332Sdes			return 0;
1769294332Sdes		sshbuf_reset(state->incoming_packet);
1770294332Sdes		if ((r = sshbuf_reserve(state->incoming_packet, block_size,
1771294332Sdes		    &cp)) != 0)
1772294332Sdes			goto out;
1773323134Sdes		if ((r = cipher_crypt(state->receive_context,
1774294332Sdes		    state->p_send.seqnr, cp, sshbuf_ptr(state->input),
1775294332Sdes		    block_size, 0, 0)) != 0)
1776294332Sdes			goto out;
1777294332Sdes		state->packlen = PEEK_U32(sshbuf_ptr(state->incoming_packet));
1778294332Sdes		if (state->packlen < 1 + 4 ||
1779294332Sdes		    state->packlen > PACKET_MAX_SIZE) {
1780124208Sdes#ifdef PACKET_DEBUG
1781294332Sdes			fprintf(stderr, "input: \n");
1782294332Sdes			sshbuf_dump(state->input, stderr);
1783294332Sdes			fprintf(stderr, "incoming_packet: \n");
1784294332Sdes			sshbuf_dump(state->incoming_packet, stderr);
1785124208Sdes#endif
1786294332Sdes			logit("Bad packet length %u.", state->packlen);
1787323129Sdes			return ssh_packet_start_discard(ssh, enc, mac, 0,
1788323129Sdes			    PACKET_MAX_SIZE);
178960573Skris		}
1790294332Sdes		if ((r = sshbuf_consume(state->input, block_size)) != 0)
1791294332Sdes			goto out;
179260573Skris	}
1793294332Sdes	DBG(debug("input: packet len %u", state->packlen+4));
1794294332Sdes
1795248619Sdes	if (aadlen) {
1796248619Sdes		/* only the payload is encrypted */
1797294332Sdes		need = state->packlen;
1798248619Sdes	} else {
1799248619Sdes		/*
1800248619Sdes		 * the payload size and the payload are encrypted, but we
1801248619Sdes		 * have a partial packet of block_size bytes
1802248619Sdes		 */
1803294332Sdes		need = 4 + state->packlen - block_size;
1804248619Sdes	}
1805248619Sdes	DBG(debug("partial packet: block %d, need %d, maclen %d, authlen %d,"
1806248619Sdes	    " aadlen %d", block_size, need, maclen, authlen, aadlen));
1807192595Sdes	if (need % block_size != 0) {
1808192595Sdes		logit("padding error: need %d block %d mod %d",
180960573Skris		    need, block_size, need % block_size);
1810323129Sdes		return ssh_packet_start_discard(ssh, enc, mac, 0,
1811323129Sdes		    PACKET_MAX_SIZE - block_size);
1812192595Sdes	}
181360573Skris	/*
181460573Skris	 * check if the entire packet has been received and
1815248619Sdes	 * decrypt into incoming_packet:
1816248619Sdes	 * 'aadlen' bytes are unencrypted, but authenticated.
1817248619Sdes	 * 'need' bytes are encrypted, followed by either
1818248619Sdes	 * 'authlen' bytes of authentication tag or
1819248619Sdes	 * 'maclen' bytes of message authentication code.
182060573Skris	 */
1821294332Sdes	if (sshbuf_len(state->input) < aadlen + need + authlen + maclen)
1822323129Sdes		return 0; /* packet is incomplete */
182360573Skris#ifdef PACKET_DEBUG
182460573Skris	fprintf(stderr, "read_poll enc/full: ");
1825294332Sdes	sshbuf_dump(state->input, stderr);
182660573Skris#endif
1827323129Sdes	/* EtM: check mac over encrypted input */
1828294332Sdes	if (mac && mac->enabled && mac->etm) {
1829323129Sdes		if ((r = mac_check(mac, state->p_read.seqnr,
1830294332Sdes		    sshbuf_ptr(state->input), aadlen + need,
1831323129Sdes		    sshbuf_ptr(state->input) + aadlen + need + authlen,
1832323129Sdes		    maclen)) != 0) {
1833323129Sdes			if (r == SSH_ERR_MAC_INVALID)
1834323129Sdes				logit("Corrupted MAC on input.");
1835294332Sdes			goto out;
1836323129Sdes		}
1837294332Sdes	}
1838294332Sdes	if ((r = sshbuf_reserve(state->incoming_packet, aadlen + need,
1839294332Sdes	    &cp)) != 0)
1840294332Sdes		goto out;
1841323134Sdes	if ((r = cipher_crypt(state->receive_context, state->p_read.seqnr, cp,
1842294332Sdes	    sshbuf_ptr(state->input), need, aadlen, authlen)) != 0)
1843294332Sdes		goto out;
1844294332Sdes	if ((r = sshbuf_consume(state->input, aadlen + need + authlen)) != 0)
1845294332Sdes		goto out;
184660573Skris	if (mac && mac->enabled) {
1847323129Sdes		/* Not EtM: check MAC over cleartext */
1848323129Sdes		if (!mac->etm && (r = mac_check(mac, state->p_read.seqnr,
1849323129Sdes		    sshbuf_ptr(state->incoming_packet),
1850323129Sdes		    sshbuf_len(state->incoming_packet),
1851323129Sdes		    sshbuf_ptr(state->input), maclen)) != 0) {
1852323129Sdes			if (r != SSH_ERR_MAC_INVALID)
1853294332Sdes				goto out;
1854192595Sdes			logit("Corrupted MAC on input.");
1855323136Sdes			if (need + block_size > PACKET_MAX_SIZE)
1856294332Sdes				return SSH_ERR_INTERNAL_ERROR;
1857294332Sdes			return ssh_packet_start_discard(ssh, enc, mac,
1858323129Sdes			    sshbuf_len(state->incoming_packet),
1859323136Sdes			    PACKET_MAX_SIZE - need - block_size);
1860192595Sdes		}
1861323129Sdes		/* Remove MAC from input buffer */
1862294332Sdes		DBG(debug("MAC #%d ok", state->p_read.seqnr));
1863294332Sdes		if ((r = sshbuf_consume(state->input, mac->mac_len)) != 0)
1864294332Sdes			goto out;
186560573Skris	}
186692555Sdes	if (seqnr_p != NULL)
1867294332Sdes		*seqnr_p = state->p_read.seqnr;
1868294332Sdes	if (++state->p_read.seqnr == 0)
1869124208Sdes		logit("incoming seqnr wraps around");
1870294332Sdes	if (++state->p_read.packets == 0)
1871294332Sdes		if (!(ssh->compat & SSH_BUG_NOREKEY))
1872294332Sdes			return SSH_ERR_NEED_REKEY;
1873294332Sdes	state->p_read.blocks += (state->packlen + 4) / block_size;
1874294332Sdes	state->p_read.bytes += state->packlen + 4;
187560573Skris
187660573Skris	/* get padlen */
1877294332Sdes	padlen = sshbuf_ptr(state->incoming_packet)[4];
187860573Skris	DBG(debug("input: padlen %d", padlen));
1879294332Sdes	if (padlen < 4)	{
1880294332Sdes		if ((r = sshpkt_disconnect(ssh,
1881294332Sdes		    "Corrupted padlen %d on input.", padlen)) != 0 ||
1882294332Sdes		    (r = ssh_packet_write_wait(ssh)) != 0)
1883294332Sdes			return r;
1884294332Sdes		return SSH_ERR_CONN_CORRUPT;
1885294332Sdes	}
188660573Skris
188760573Skris	/* skip packet size + padlen, discard padding */
1888294332Sdes	if ((r = sshbuf_consume(state->incoming_packet, 4 + 1)) != 0 ||
1889294332Sdes	    ((r = sshbuf_consume_end(state->incoming_packet, padlen)) != 0))
1890294332Sdes		goto out;
189160573Skris
1892294332Sdes	DBG(debug("input: len before de-compress %zd",
1893294332Sdes	    sshbuf_len(state->incoming_packet)));
189460573Skris	if (comp && comp->enabled) {
1895294332Sdes		sshbuf_reset(state->compression_buffer);
1896294332Sdes		if ((r = uncompress_buffer(ssh, state->incoming_packet,
1897294332Sdes		    state->compression_buffer)) != 0)
1898294332Sdes			goto out;
1899294332Sdes		sshbuf_reset(state->incoming_packet);
1900294332Sdes		if ((r = sshbuf_putb(state->incoming_packet,
1901294332Sdes		    state->compression_buffer)) != 0)
1902294332Sdes			goto out;
1903294332Sdes		DBG(debug("input: len after de-compress %zd",
1904294332Sdes		    sshbuf_len(state->incoming_packet)));
190560573Skris	}
190660573Skris	/*
190760573Skris	 * get packet type, implies consume.
190860573Skris	 * return length of payload (without type field)
190960573Skris	 */
1910294332Sdes	if ((r = sshbuf_get_u8(state->incoming_packet, typep)) != 0)
1911294332Sdes		goto out;
1912296633Sdes	if (ssh_packet_log_type(*typep))
1913296633Sdes		debug3("receive packet: type %u", *typep);
1914294332Sdes	if (*typep < SSH2_MSG_MIN || *typep >= SSH2_MSG_LOCAL_MIN) {
1915294332Sdes		if ((r = sshpkt_disconnect(ssh,
1916294332Sdes		    "Invalid ssh2 packet type: %d", *typep)) != 0 ||
1917294332Sdes		    (r = ssh_packet_write_wait(ssh)) != 0)
1918294332Sdes			return r;
1919294332Sdes		return SSH_ERR_PROTOCOL_ERROR;
1920294332Sdes	}
1921323134Sdes	if (state->hook_in != NULL &&
1922323134Sdes	    (r = state->hook_in(ssh, state->incoming_packet, typep,
1923323134Sdes	    state->hook_in_ctx)) != 0)
1924323134Sdes		return r;
1925323134Sdes	if (*typep == SSH2_MSG_USERAUTH_SUCCESS && !state->server_side)
1926294332Sdes		r = ssh_packet_enable_delayed_compress(ssh);
1927294332Sdes	else
1928294332Sdes		r = 0;
192960573Skris#ifdef PACKET_DEBUG
1930294332Sdes	fprintf(stderr, "read/plain[%d]:\r\n", *typep);
1931294332Sdes	sshbuf_dump(state->incoming_packet, stderr);
193260573Skris#endif
193392555Sdes	/* reset for next packet */
1934294332Sdes	state->packlen = 0;
1935296633Sdes
1936296633Sdes	/* do we need to rekey? */
1937296633Sdes	if (ssh_packet_need_rekeying(ssh, 0)) {
1938296633Sdes		debug3("%s: rekex triggered", __func__);
1939296633Sdes		if ((r = kex_start_rekex(ssh)) != 0)
1940296633Sdes			return r;
1941296633Sdes	}
1942294332Sdes out:
1943294332Sdes	return r;
194457429Smarkm}
194557429Smarkm
194660573Skrisint
1947294332Sdesssh_packet_read_poll_seqnr(struct ssh *ssh, u_char *typep, u_int32_t *seqnr_p)
194860573Skris{
1949294332Sdes	struct session_state *state = ssh->state;
195099060Sdes	u_int reason, seqnr;
1951294332Sdes	int r;
1952294332Sdes	u_char *msg;
195392555Sdes
195460573Skris	for (;;) {
1955294332Sdes		msg = NULL;
195692555Sdes		if (compat20) {
1957294332Sdes			r = ssh_packet_read_poll2(ssh, typep, seqnr_p);
1958294332Sdes			if (r != 0)
1959294332Sdes				return r;
1960294332Sdes			if (*typep) {
1961294332Sdes				state->keep_alive_timeouts = 0;
1962294332Sdes				DBG(debug("received packet type %d", *typep));
1963181111Sdes			}
1964294332Sdes			switch (*typep) {
196560573Skris			case SSH2_MSG_IGNORE:
1966181111Sdes				debug3("Received SSH2_MSG_IGNORE");
196760573Skris				break;
196860573Skris			case SSH2_MSG_DEBUG:
1969294332Sdes				if ((r = sshpkt_get_u8(ssh, NULL)) != 0 ||
1970294332Sdes				    (r = sshpkt_get_string(ssh, &msg, NULL)) != 0 ||
1971294332Sdes				    (r = sshpkt_get_string(ssh, NULL, NULL)) != 0) {
1972296633Sdes					free(msg);
1973294332Sdes					return r;
1974294332Sdes				}
197560573Skris				debug("Remote: %.900s", msg);
1976255767Sdes				free(msg);
197760573Skris				break;
197860573Skris			case SSH2_MSG_DISCONNECT:
1979294332Sdes				if ((r = sshpkt_get_u32(ssh, &reason)) != 0 ||
1980294332Sdes				    (r = sshpkt_get_string(ssh, &msg, NULL)) != 0)
1981294332Sdes					return r;
1982249475Sdes				/* Ignore normal client exit notifications */
1983294332Sdes				do_log2(ssh->state->server_side &&
1984249475Sdes				    reason == SSH2_DISCONNECT_BY_APPLICATION ?
1985250739Sdes				    SYSLOG_LEVEL_INFO : SYSLOG_LEVEL_ERROR,
1986296633Sdes				    "Received disconnect from %s port %d:"
1987296633Sdes				    "%u: %.400s", ssh_remote_ipaddr(ssh),
1988296633Sdes				    ssh_remote_port(ssh), reason, msg);
1989255767Sdes				free(msg);
1990294332Sdes				return SSH_ERR_DISCONNECTED;
199192555Sdes			case SSH2_MSG_UNIMPLEMENTED:
1992294332Sdes				if ((r = sshpkt_get_u32(ssh, &seqnr)) != 0)
1993294332Sdes					return r;
199499060Sdes				debug("Received SSH2_MSG_UNIMPLEMENTED for %u",
199599060Sdes				    seqnr);
199692555Sdes				break;
199760573Skris			default:
1998294332Sdes				return 0;
199976259Sgreen			}
200060573Skris		} else {
2001294332Sdes			r = ssh_packet_read_poll1(ssh, typep);
2002294332Sdes			switch (*typep) {
2003255767Sdes			case SSH_MSG_NONE:
2004255767Sdes				return SSH_MSG_NONE;
200560573Skris			case SSH_MSG_IGNORE:
200660573Skris				break;
200760573Skris			case SSH_MSG_DEBUG:
2008294332Sdes				if ((r = sshpkt_get_string(ssh, &msg, NULL)) != 0)
2009294332Sdes					return r;
201060573Skris				debug("Remote: %.900s", msg);
2011255767Sdes				free(msg);
201260573Skris				break;
201360573Skris			case SSH_MSG_DISCONNECT:
2014294332Sdes				if ((r = sshpkt_get_string(ssh, &msg, NULL)) != 0)
2015294332Sdes					return r;
2016296633Sdes				logit("Received disconnect from %s port %d: "
2017296633Sdes				    "%.400s", ssh_remote_ipaddr(ssh),
2018296633Sdes				    ssh_remote_port(ssh), msg);
2019294332Sdes				free(msg);
2020294332Sdes				return SSH_ERR_DISCONNECTED;
202160573Skris			default:
2022294332Sdes				DBG(debug("received packet type %d", *typep));
2023294332Sdes				return 0;
202476259Sgreen			}
202560573Skris		}
202660573Skris	}
202760573Skris}
202860573Skris
202957429Smarkm/*
203057429Smarkm * Buffers the given amount of input characters.  This is intended to be used
203157429Smarkm * together with packet_read_poll.
203257429Smarkm */
203357429Smarkm
2034294332Sdesint
2035294332Sdesssh_packet_process_incoming(struct ssh *ssh, const char *buf, u_int len)
203657429Smarkm{
2037294332Sdes	struct session_state *state = ssh->state;
2038294332Sdes	int r;
2039294332Sdes
2040294332Sdes	if (state->packet_discard) {
2041294332Sdes		state->keep_alive_timeouts = 0; /* ?? */
2042294332Sdes		if (len >= state->packet_discard) {
2043294332Sdes			if ((r = ssh_packet_stop_discard(ssh)) != 0)
2044294332Sdes				return r;
2045294332Sdes		}
2046294332Sdes		state->packet_discard -= len;
2047294332Sdes		return 0;
2048192595Sdes	}
2049294332Sdes	if ((r = sshbuf_put(ssh->state->input, buf, len)) != 0)
2050294332Sdes		return r;
205157429Smarkm
2052294332Sdes	return 0;
205357429Smarkm}
205457429Smarkm
205560573Skrisint
2056294332Sdesssh_packet_remaining(struct ssh *ssh)
205760573Skris{
2058294332Sdes	return sshbuf_len(ssh->state->incoming_packet);
205960573Skris}
206060573Skris
206157429Smarkm/*
206257429Smarkm * Sends a diagnostic message from the server to the client.  This message
206357429Smarkm * can be sent at any time (but not while constructing another message). The
206457429Smarkm * message is printed immediately, but only if the client is being executed
206557429Smarkm * in verbose mode.  These messages are primarily intended to ease debugging
206657429Smarkm * authentication problems.   The length of the formatted message must not
2067294332Sdes * exceed 1024 bytes.  This will automatically call ssh_packet_write_wait.
206857429Smarkm */
206957429Smarkmvoid
2070294332Sdesssh_packet_send_debug(struct ssh *ssh, const char *fmt,...)
207157429Smarkm{
207257429Smarkm	char buf[1024];
207357429Smarkm	va_list args;
2074294332Sdes	int r;
207557429Smarkm
2076294332Sdes	if (compat20 && (ssh->compat & SSH_BUG_DEBUG))
207776259Sgreen		return;
207876259Sgreen
207957429Smarkm	va_start(args, fmt);
208057429Smarkm	vsnprintf(buf, sizeof(buf), fmt, args);
208157429Smarkm	va_end(args);
208257429Smarkm
208360573Skris	if (compat20) {
2084294332Sdes		if ((r = sshpkt_start(ssh, SSH2_MSG_DEBUG)) != 0 ||
2085294332Sdes		    (r = sshpkt_put_u8(ssh, 0)) != 0 || /* always display */
2086294332Sdes		    (r = sshpkt_put_cstring(ssh, buf)) != 0 ||
2087294332Sdes		    (r = sshpkt_put_cstring(ssh, "")) != 0 ||
2088294332Sdes		    (r = sshpkt_send(ssh)) != 0)
2089294332Sdes			fatal("%s: %s", __func__, ssh_err(r));
209060573Skris	} else {
2091294332Sdes		if ((r = sshpkt_start(ssh, SSH_MSG_DEBUG)) != 0 ||
2092294332Sdes		    (r = sshpkt_put_cstring(ssh, buf)) != 0 ||
2093294332Sdes		    (r = sshpkt_send(ssh)) != 0)
2094294332Sdes			fatal("%s: %s", __func__, ssh_err(r));
209560573Skris	}
2096294332Sdes	if ((r = ssh_packet_write_wait(ssh)) != 0)
2097294332Sdes		fatal("%s: %s", __func__, ssh_err(r));
209857429Smarkm}
209957429Smarkm
2100323136Sdesstatic void
2101323136Sdesfmt_connection_id(struct ssh *ssh, char *s, size_t l)
2102323136Sdes{
2103323136Sdes	snprintf(s, l, "%.200s%s%s port %d",
2104323136Sdes	    ssh->log_preamble ? ssh->log_preamble : "",
2105323136Sdes	    ssh->log_preamble ? " " : "",
2106323136Sdes	    ssh_remote_ipaddr(ssh), ssh_remote_port(ssh));
2107323136Sdes}
2108323136Sdes
210957429Smarkm/*
2110294332Sdes * Pretty-print connection-terminating errors and exit.
2111294332Sdes */
2112294332Sdesvoid
2113294332Sdessshpkt_fatal(struct ssh *ssh, const char *tag, int r)
2114294332Sdes{
2115323136Sdes	char remote_id[512];
2116323136Sdes
2117323136Sdes	fmt_connection_id(ssh, remote_id, sizeof(remote_id));
2118323136Sdes
2119294332Sdes	switch (r) {
2120294332Sdes	case SSH_ERR_CONN_CLOSED:
2121323136Sdes		logdie("Connection closed by %s", remote_id);
2122294332Sdes	case SSH_ERR_CONN_TIMEOUT:
2123323136Sdes		logdie("Connection %s %s timed out",
2124323136Sdes		    ssh->state->server_side ? "from" : "to", remote_id);
2125294336Sdes	case SSH_ERR_DISCONNECTED:
2126323136Sdes		logdie("Disconnected from %s", remote_id);
2127294336Sdes	case SSH_ERR_SYSTEM_ERROR:
2128323129Sdes		if (errno == ECONNRESET)
2129323136Sdes			logdie("Connection reset by %s", remote_id);
2130294336Sdes		/* FALLTHROUGH */
2131294464Sdes	case SSH_ERR_NO_CIPHER_ALG_MATCH:
2132294464Sdes	case SSH_ERR_NO_MAC_ALG_MATCH:
2133294464Sdes	case SSH_ERR_NO_COMPRESS_ALG_MATCH:
2134294464Sdes	case SSH_ERR_NO_KEX_ALG_MATCH:
2135294464Sdes	case SSH_ERR_NO_HOSTKEY_ALG_MATCH:
2136294464Sdes		if (ssh && ssh->kex && ssh->kex->failed_choice) {
2137318402Slidl			BLACKLIST_NOTIFY(BLACKLIST_AUTH_FAIL, "ssh");
2138323136Sdes			logdie("Unable to negotiate with %s: %s. "
2139323136Sdes			    "Their offer: %s", remote_id, ssh_err(r),
2140296633Sdes			    ssh->kex->failed_choice);
2141294464Sdes		}
2142294464Sdes		/* FALLTHROUGH */
2143294332Sdes	default:
2144323136Sdes		logdie("%s%sConnection %s %s: %s",
2145294332Sdes		    tag != NULL ? tag : "", tag != NULL ? ": " : "",
2146296633Sdes		    ssh->state->server_side ? "from" : "to",
2147323136Sdes		    remote_id, ssh_err(r));
2148294332Sdes	}
2149294332Sdes}
2150294332Sdes
2151294332Sdes/*
215257429Smarkm * Logs the error plus constructs and sends a disconnect packet, closes the
215357429Smarkm * connection, and exits.  This function never returns. The error message
215457429Smarkm * should not contain a newline.  The length of the formatted message must
215557429Smarkm * not exceed 1024 bytes.
215657429Smarkm */
215757429Smarkmvoid
2158294332Sdesssh_packet_disconnect(struct ssh *ssh, const char *fmt,...)
215957429Smarkm{
2160323136Sdes	char buf[1024], remote_id[512];
216157429Smarkm	va_list args;
216257429Smarkm	static int disconnecting = 0;
2163294332Sdes	int r;
2164106121Sdes
216557429Smarkm	if (disconnecting)	/* Guard against recursive invocations. */
216657429Smarkm		fatal("packet_disconnect called recursively.");
216757429Smarkm	disconnecting = 1;
216857429Smarkm
216957429Smarkm	/*
217057429Smarkm	 * Format the message.  Note that the caller must make sure the
217157429Smarkm	 * message is of limited size.
217257429Smarkm	 */
2173323136Sdes	fmt_connection_id(ssh, remote_id, sizeof(remote_id));
217457429Smarkm	va_start(args, fmt);
217557429Smarkm	vsnprintf(buf, sizeof(buf), fmt, args);
217657429Smarkm	va_end(args);
217757429Smarkm
2178113908Sdes	/* Display the error locally */
2179323136Sdes	logit("Disconnecting %s: %.100s", remote_id, buf);
2180113908Sdes
2181294332Sdes	/*
2182294332Sdes	 * Send the disconnect message to the other side, and wait
2183294332Sdes	 * for it to get sent.
2184294332Sdes	 */
2185294332Sdes	if ((r = sshpkt_disconnect(ssh, "%s", buf)) != 0)
2186294332Sdes		sshpkt_fatal(ssh, __func__, r);
218757429Smarkm
2188294332Sdes	if ((r = ssh_packet_write_wait(ssh)) != 0)
2189294332Sdes		sshpkt_fatal(ssh, __func__, r);
219057429Smarkm
219157429Smarkm	/* Close the connection. */
2192294332Sdes	ssh_packet_close(ssh);
2193126274Sdes	cleanup_exit(255);
219457429Smarkm}
219557429Smarkm
2196294332Sdes/*
2197294332Sdes * Checks if there is any buffered output, and tries to write some of
2198294332Sdes * the output.
2199294332Sdes */
2200294332Sdesint
2201294332Sdesssh_packet_write_poll(struct ssh *ssh)
220257429Smarkm{
2203294332Sdes	struct session_state *state = ssh->state;
2204294332Sdes	int len = sshbuf_len(state->output);
2205296633Sdes	int r;
2206106121Sdes
220757429Smarkm	if (len > 0) {
2208296633Sdes		len = write(state->connection_out,
2209296633Sdes		    sshbuf_ptr(state->output), len);
2210181111Sdes		if (len == -1) {
2211181111Sdes			if (errno == EINTR || errno == EAGAIN ||
2212181111Sdes			    errno == EWOULDBLOCK)
2213294332Sdes				return 0;
2214294332Sdes			return SSH_ERR_SYSTEM_ERROR;
221557429Smarkm		}
2216296633Sdes		if (len == 0)
2217294332Sdes			return SSH_ERR_CONN_CLOSED;
2218294332Sdes		if ((r = sshbuf_consume(state->output, len)) != 0)
2219294332Sdes			return r;
222057429Smarkm	}
2221294332Sdes	return 0;
222257429Smarkm}
222357429Smarkm
222457429Smarkm/*
222557429Smarkm * Calls packet_write_poll repeatedly until all pending output data has been
222657429Smarkm * written.
222757429Smarkm */
2228294332Sdesint
2229294332Sdesssh_packet_write_wait(struct ssh *ssh)
223057429Smarkm{
223176259Sgreen	fd_set *setp;
2232294332Sdes	int ret, r, ms_remain = 0;
2233181111Sdes	struct timeval start, timeout, *timeoutp = NULL;
2234294332Sdes	struct session_state *state = ssh->state;
223576259Sgreen
2236294496Sdes	setp = calloc(howmany(state->connection_out + 1,
2237197679Sdes	    NFDBITS), sizeof(fd_mask));
2238294332Sdes	if (setp == NULL)
2239294332Sdes		return SSH_ERR_ALLOC_FAIL;
2240296633Sdes	if ((r = ssh_packet_write_poll(ssh)) != 0) {
2241296633Sdes		free(setp);
2242296633Sdes		return r;
2243296633Sdes	}
2244294332Sdes	while (ssh_packet_have_data_to_write(ssh)) {
2245294332Sdes		memset(setp, 0, howmany(state->connection_out + 1,
2246197679Sdes		    NFDBITS) * sizeof(fd_mask));
2247294332Sdes		FD_SET(state->connection_out, setp);
2248181111Sdes
2249294332Sdes		if (state->packet_timeout_ms > 0) {
2250294332Sdes			ms_remain = state->packet_timeout_ms;
2251181111Sdes			timeoutp = &timeout;
2252181111Sdes		}
2253181111Sdes		for (;;) {
2254294332Sdes			if (state->packet_timeout_ms != -1) {
2255181111Sdes				ms_to_timeval(&timeout, ms_remain);
2256181111Sdes				gettimeofday(&start, NULL);
2257181111Sdes			}
2258294332Sdes			if ((ret = select(state->connection_out + 1,
2259197679Sdes			    NULL, setp, NULL, timeoutp)) >= 0)
2260181111Sdes				break;
2261197679Sdes			if (errno != EAGAIN && errno != EINTR &&
2262181111Sdes			    errno != EWOULDBLOCK)
2263181111Sdes				break;
2264294332Sdes			if (state->packet_timeout_ms == -1)
2265181111Sdes				continue;
2266181111Sdes			ms_subtract_diff(&start, &ms_remain);
2267181111Sdes			if (ms_remain <= 0) {
2268181111Sdes				ret = 0;
2269181111Sdes				break;
2270181111Sdes			}
2271181111Sdes		}
2272181111Sdes		if (ret == 0) {
2273294332Sdes			free(setp);
2274294332Sdes			return SSH_ERR_CONN_TIMEOUT;
2275181111Sdes		}
2276294332Sdes		if ((r = ssh_packet_write_poll(ssh)) != 0) {
2277294332Sdes			free(setp);
2278294332Sdes			return r;
2279294332Sdes		}
228057429Smarkm	}
2281255767Sdes	free(setp);
2282294332Sdes	return 0;
228357429Smarkm}
228457429Smarkm
228557429Smarkm/* Returns true if there is buffered data to write to the connection. */
228657429Smarkm
228757429Smarkmint
2288294332Sdesssh_packet_have_data_to_write(struct ssh *ssh)
228957429Smarkm{
2290294332Sdes	return sshbuf_len(ssh->state->output) != 0;
229157429Smarkm}
229257429Smarkm
229357429Smarkm/* Returns true if there is not too much data to write to the connection. */
229457429Smarkm
229557429Smarkmint
2296294332Sdesssh_packet_not_very_much_data_to_write(struct ssh *ssh)
229757429Smarkm{
2298294332Sdes	if (ssh->state->interactive_mode)
2299294332Sdes		return sshbuf_len(ssh->state->output) < 16384;
230057429Smarkm	else
2301294332Sdes		return sshbuf_len(ssh->state->output) < 128 * 1024;
230257429Smarkm}
230357429Smarkm
2304294332Sdesvoid
2305294332Sdesssh_packet_set_tos(struct ssh *ssh, int tos)
2306113908Sdes{
2307226046Sdes#ifndef IP_TOS_IS_BROKEN
2308294332Sdes	if (!ssh_packet_connection_is_on_socket(ssh))
2309113908Sdes		return;
2310294332Sdes	switch (ssh_packet_connection_af(ssh)) {
2311226046Sdes# ifdef IP_TOS
2312226046Sdes	case AF_INET:
2313226046Sdes		debug3("%s: set IP_TOS 0x%02x", __func__, tos);
2314294332Sdes		if (setsockopt(ssh->state->connection_in,
2315226046Sdes		    IPPROTO_IP, IP_TOS, &tos, sizeof(tos)) < 0)
2316226046Sdes			error("setsockopt IP_TOS %d: %.100s:",
2317226046Sdes			    tos, strerror(errno));
2318226046Sdes		break;
2319226046Sdes# endif /* IP_TOS */
2320226046Sdes# ifdef IPV6_TCLASS
2321226046Sdes	case AF_INET6:
2322226046Sdes		debug3("%s: set IPV6_TCLASS 0x%02x", __func__, tos);
2323294332Sdes		if (setsockopt(ssh->state->connection_in,
2324226046Sdes		    IPPROTO_IPV6, IPV6_TCLASS, &tos, sizeof(tos)) < 0)
2325226046Sdes			error("setsockopt IPV6_TCLASS %d: %.100s:",
2326226046Sdes			    tos, strerror(errno));
2327226046Sdes		break;
2328226046Sdes# endif /* IPV6_TCLASS */
2329226046Sdes	}
2330226046Sdes#endif /* IP_TOS_IS_BROKEN */
2331113908Sdes}
2332113908Sdes
233357429Smarkm/* Informs that the current session is interactive.  Sets IP flags for that. */
233457429Smarkm
233557429Smarkmvoid
2336294332Sdesssh_packet_set_interactive(struct ssh *ssh, int interactive, int qos_interactive, int qos_bulk)
233757429Smarkm{
2338294332Sdes	struct session_state *state = ssh->state;
2339294332Sdes
2340294332Sdes	if (state->set_interactive_called)
234176259Sgreen		return;
2342294332Sdes	state->set_interactive_called = 1;
234376259Sgreen
234457429Smarkm	/* Record that we are in interactive mode. */
2345294332Sdes	state->interactive_mode = interactive;
234657429Smarkm
234757429Smarkm	/* Only set socket options if using a socket.  */
2348294332Sdes	if (!ssh_packet_connection_is_on_socket(ssh))
2349116791Sdes		return;
2350294332Sdes	set_nodelay(state->connection_in);
2351294332Sdes	ssh_packet_set_tos(ssh, interactive ? qos_interactive :
2352294332Sdes	    qos_bulk);
235357429Smarkm}
235457429Smarkm
235557429Smarkm/* Returns true if the current connection is interactive. */
235657429Smarkm
235757429Smarkmint
2358294332Sdesssh_packet_is_interactive(struct ssh *ssh)
235957429Smarkm{
2360294332Sdes	return ssh->state->interactive_mode;
236157429Smarkm}
236257429Smarkm
2363137015Sdesint
2364294332Sdesssh_packet_set_maxsize(struct ssh *ssh, u_int s)
236557429Smarkm{
2366294332Sdes	struct session_state *state = ssh->state;
2367294332Sdes
2368294332Sdes	if (state->set_maxsize_called) {
2369124208Sdes		logit("packet_set_maxsize: called twice: old %d new %d",
2370294332Sdes		    state->max_packet_size, s);
237157429Smarkm		return -1;
237257429Smarkm	}
237357429Smarkm	if (s < 4 * 1024 || s > 1024 * 1024) {
2374124208Sdes		logit("packet_set_maxsize: bad size %d", s);
237557429Smarkm		return -1;
237657429Smarkm	}
2377294332Sdes	state->set_maxsize_called = 1;
237892555Sdes	debug("packet_set_maxsize: setting to %d", s);
2379294332Sdes	state->max_packet_size = s;
238057429Smarkm	return s;
238157429Smarkm}
238276259Sgreen
2383197679Sdesint
2384294332Sdesssh_packet_inc_alive_timeouts(struct ssh *ssh)
2385197679Sdes{
2386294332Sdes	return ++ssh->state->keep_alive_timeouts;
2387197679Sdes}
2388197679Sdes
2389197679Sdesvoid
2390294332Sdesssh_packet_set_alive_timeouts(struct ssh *ssh, int ka)
2391197679Sdes{
2392294332Sdes	ssh->state->keep_alive_timeouts = ka;
2393197679Sdes}
2394197679Sdes
2395197679Sdesu_int
2396294332Sdesssh_packet_get_maxsize(struct ssh *ssh)
2397197679Sdes{
2398294332Sdes	return ssh->state->max_packet_size;
2399197679Sdes}
2400197679Sdes
240176259Sgreen/*
240276259Sgreen * 9.2.  Ignored Data Message
240376259Sgreen *
240476259Sgreen *   byte      SSH_MSG_IGNORE
240576259Sgreen *   string    data
240676259Sgreen *
240776259Sgreen * All implementations MUST understand (and ignore) this message at any
240876259Sgreen * time (after receiving the protocol version). No implementation is
240976259Sgreen * required to send them. This message can be used as an additional
241076259Sgreen * protection measure against advanced traffic analysis techniques.
241176259Sgreen */
241276259Sgreenvoid
2413294332Sdesssh_packet_send_ignore(struct ssh *ssh, int nbytes)
241476259Sgreen{
2415137015Sdes	u_int32_t rnd = 0;
2416294332Sdes	int r, i;
241776259Sgreen
2418294332Sdes	if ((r = sshpkt_start(ssh, compat20 ?
2419294332Sdes	    SSH2_MSG_IGNORE : SSH_MSG_IGNORE)) != 0 ||
2420294332Sdes	    (r = sshpkt_put_u32(ssh, nbytes)) != 0)
2421294332Sdes		fatal("%s: %s", __func__, ssh_err(r));
242292555Sdes	for (i = 0; i < nbytes; i++) {
242376259Sgreen		if (i % 4 == 0)
2424137015Sdes			rnd = arc4random();
2425294332Sdes		if ((r = sshpkt_put_u8(ssh, (u_char)rnd & 0xff)) != 0)
2426294332Sdes			fatal("%s: %s", __func__, ssh_err(r));
2427137015Sdes		rnd >>= 8;
242876259Sgreen	}
242976259Sgreen}
2430124208Sdes
2431124208Sdesvoid
2432323136Sdesssh_packet_set_rekey_limits(struct ssh *ssh, u_int64_t bytes, u_int32_t seconds)
2433124208Sdes{
2434323136Sdes	debug3("rekey after %llu bytes, %u seconds", (unsigned long long)bytes,
2435323136Sdes	    (unsigned int)seconds);
2436294332Sdes	ssh->state->rekey_limit = bytes;
2437294332Sdes	ssh->state->rekey_interval = seconds;
2438124208Sdes}
2439149749Sdes
2440255767Sdestime_t
2441294332Sdesssh_packet_get_rekey_timeout(struct ssh *ssh)
2442255767Sdes{
2443255767Sdes	time_t seconds;
2444255767Sdes
2445294332Sdes	seconds = ssh->state->rekey_time + ssh->state->rekey_interval -
2446255767Sdes	    monotime();
2447255767Sdes	return (seconds <= 0 ? 1 : seconds);
2448255767Sdes}
2449255767Sdes
2450149749Sdesvoid
2451294332Sdesssh_packet_set_server(struct ssh *ssh)
2452149749Sdes{
2453294332Sdes	ssh->state->server_side = 1;
2454149749Sdes}
2455149749Sdes
2456149749Sdesvoid
2457294332Sdesssh_packet_set_authenticated(struct ssh *ssh)
2458149749Sdes{
2459294332Sdes	ssh->state->after_authentication = 1;
2460149749Sdes}
2461197679Sdes
2462197679Sdesvoid *
2463294332Sdesssh_packet_get_input(struct ssh *ssh)
2464197679Sdes{
2465294332Sdes	return (void *)ssh->state->input;
2466197679Sdes}
2467197679Sdes
2468197679Sdesvoid *
2469294332Sdesssh_packet_get_output(struct ssh *ssh)
2470197679Sdes{
2471294332Sdes	return (void *)ssh->state->output;
2472197679Sdes}
2473197679Sdes
2474294328Sdes/* Reset after_authentication and reset compression in post-auth privsep */
2475294332Sdesstatic int
2476294332Sdesssh_packet_set_postauth(struct ssh *ssh)
2477294328Sdes{
2478323134Sdes	int r;
2479294328Sdes
2480294328Sdes	debug("%s: called", __func__);
2481294328Sdes	/* This was set in net child, but is not visible in user child */
2482294332Sdes	ssh->state->after_authentication = 1;
2483294332Sdes	ssh->state->rekeying = 0;
2484323134Sdes	if ((r = ssh_packet_enable_delayed_compress(ssh)) != 0)
2485323134Sdes		return r;
2486294332Sdes	return 0;
2487294328Sdes}
2488294332Sdes
2489294332Sdes/* Packet state (de-)serialization for privsep */
2490294332Sdes
2491294332Sdes/* turn kex into a blob for packet state serialization */
2492294332Sdesstatic int
2493294332Sdeskex_to_blob(struct sshbuf *m, struct kex *kex)
2494294332Sdes{
2495294332Sdes	int r;
2496294332Sdes
2497294332Sdes	if ((r = sshbuf_put_string(m, kex->session_id,
2498294332Sdes	    kex->session_id_len)) != 0 ||
2499294332Sdes	    (r = sshbuf_put_u32(m, kex->we_need)) != 0 ||
2500294332Sdes	    (r = sshbuf_put_u32(m, kex->hostkey_type)) != 0 ||
2501294332Sdes	    (r = sshbuf_put_u32(m, kex->kex_type)) != 0 ||
2502294332Sdes	    (r = sshbuf_put_stringb(m, kex->my)) != 0 ||
2503294332Sdes	    (r = sshbuf_put_stringb(m, kex->peer)) != 0 ||
2504294332Sdes	    (r = sshbuf_put_u32(m, kex->flags)) != 0 ||
2505294332Sdes	    (r = sshbuf_put_cstring(m, kex->client_version_string)) != 0 ||
2506294332Sdes	    (r = sshbuf_put_cstring(m, kex->server_version_string)) != 0)
2507294332Sdes		return r;
2508294332Sdes	return 0;
2509294332Sdes}
2510294332Sdes
2511294332Sdes/* turn key exchange results into a blob for packet state serialization */
2512294332Sdesstatic int
2513294332Sdesnewkeys_to_blob(struct sshbuf *m, struct ssh *ssh, int mode)
2514294332Sdes{
2515294332Sdes	struct sshbuf *b;
2516294332Sdes	struct sshcipher_ctx *cc;
2517294332Sdes	struct sshcomp *comp;
2518294332Sdes	struct sshenc *enc;
2519294332Sdes	struct sshmac *mac;
2520294332Sdes	struct newkeys *newkey;
2521294332Sdes	int r;
2522294332Sdes
2523294332Sdes	if ((newkey = ssh->state->newkeys[mode]) == NULL)
2524294332Sdes		return SSH_ERR_INTERNAL_ERROR;
2525294332Sdes	enc = &newkey->enc;
2526294332Sdes	mac = &newkey->mac;
2527294332Sdes	comp = &newkey->comp;
2528323134Sdes	cc = (mode == MODE_OUT) ? ssh->state->send_context :
2529323134Sdes	    ssh->state->receive_context;
2530294332Sdes	if ((r = cipher_get_keyiv(cc, enc->iv, enc->iv_len)) != 0)
2531294332Sdes		return r;
2532294332Sdes	if ((b = sshbuf_new()) == NULL)
2533294332Sdes		return SSH_ERR_ALLOC_FAIL;
2534294332Sdes	/* The cipher struct is constant and shared, you export pointer */
2535294332Sdes	if ((r = sshbuf_put_cstring(b, enc->name)) != 0 ||
2536294332Sdes	    (r = sshbuf_put(b, &enc->cipher, sizeof(enc->cipher))) != 0 ||
2537294332Sdes	    (r = sshbuf_put_u32(b, enc->enabled)) != 0 ||
2538294332Sdes	    (r = sshbuf_put_u32(b, enc->block_size)) != 0 ||
2539294332Sdes	    (r = sshbuf_put_string(b, enc->key, enc->key_len)) != 0 ||
2540294332Sdes	    (r = sshbuf_put_string(b, enc->iv, enc->iv_len)) != 0)
2541294332Sdes		goto out;
2542294332Sdes	if (cipher_authlen(enc->cipher) == 0) {
2543294332Sdes		if ((r = sshbuf_put_cstring(b, mac->name)) != 0 ||
2544294332Sdes		    (r = sshbuf_put_u32(b, mac->enabled)) != 0 ||
2545294332Sdes		    (r = sshbuf_put_string(b, mac->key, mac->key_len)) != 0)
2546294332Sdes			goto out;
2547294332Sdes	}
2548294332Sdes	if ((r = sshbuf_put_u32(b, comp->type)) != 0 ||
2549294332Sdes	    (r = sshbuf_put_cstring(b, comp->name)) != 0)
2550294332Sdes		goto out;
2551294332Sdes	r = sshbuf_put_stringb(m, b);
2552294332Sdes out:
2553296633Sdes	sshbuf_free(b);
2554294332Sdes	return r;
2555294332Sdes}
2556294332Sdes
2557294332Sdes/* serialize packet state into a blob */
2558294332Sdesint
2559294332Sdesssh_packet_get_state(struct ssh *ssh, struct sshbuf *m)
2560294332Sdes{
2561294332Sdes	struct session_state *state = ssh->state;
2562294332Sdes	u_char *p;
2563294332Sdes	size_t slen, rlen;
2564294332Sdes	int r, ssh1cipher;
2565294332Sdes
2566294332Sdes	if (!compat20) {
2567323134Sdes		ssh1cipher = cipher_ctx_get_number(state->receive_context);
2568323134Sdes		slen = cipher_get_keyiv_len(state->send_context);
2569323134Sdes		rlen = cipher_get_keyiv_len(state->receive_context);
2570294332Sdes		if ((r = sshbuf_put_u32(m, state->remote_protocol_flags)) != 0 ||
2571294332Sdes		    (r = sshbuf_put_u32(m, ssh1cipher)) != 0 ||
2572294332Sdes		    (r = sshbuf_put_string(m, state->ssh1_key, state->ssh1_keylen)) != 0 ||
2573294332Sdes		    (r = sshbuf_put_u32(m, slen)) != 0 ||
2574294332Sdes		    (r = sshbuf_reserve(m, slen, &p)) != 0 ||
2575323134Sdes		    (r = cipher_get_keyiv(state->send_context, p, slen)) != 0 ||
2576294332Sdes		    (r = sshbuf_put_u32(m, rlen)) != 0 ||
2577294332Sdes		    (r = sshbuf_reserve(m, rlen, &p)) != 0 ||
2578323134Sdes		    (r = cipher_get_keyiv(state->receive_context, p, rlen)) != 0)
2579294332Sdes			return r;
2580294332Sdes	} else {
2581294332Sdes		if ((r = kex_to_blob(m, ssh->kex)) != 0 ||
2582294332Sdes		    (r = newkeys_to_blob(m, ssh, MODE_OUT)) != 0 ||
2583294332Sdes		    (r = newkeys_to_blob(m, ssh, MODE_IN)) != 0 ||
2584296633Sdes		    (r = sshbuf_put_u64(m, state->rekey_limit)) != 0 ||
2585294332Sdes		    (r = sshbuf_put_u32(m, state->rekey_interval)) != 0 ||
2586294332Sdes		    (r = sshbuf_put_u32(m, state->p_send.seqnr)) != 0 ||
2587294332Sdes		    (r = sshbuf_put_u64(m, state->p_send.blocks)) != 0 ||
2588294332Sdes		    (r = sshbuf_put_u32(m, state->p_send.packets)) != 0 ||
2589294332Sdes		    (r = sshbuf_put_u64(m, state->p_send.bytes)) != 0 ||
2590294332Sdes		    (r = sshbuf_put_u32(m, state->p_read.seqnr)) != 0 ||
2591294332Sdes		    (r = sshbuf_put_u64(m, state->p_read.blocks)) != 0 ||
2592294332Sdes		    (r = sshbuf_put_u32(m, state->p_read.packets)) != 0 ||
2593294332Sdes		    (r = sshbuf_put_u64(m, state->p_read.bytes)) != 0)
2594294332Sdes			return r;
2595294332Sdes	}
2596294332Sdes
2597323134Sdes	slen = cipher_get_keycontext(state->send_context, NULL);
2598323134Sdes	rlen = cipher_get_keycontext(state->receive_context, NULL);
2599294332Sdes	if ((r = sshbuf_put_u32(m, slen)) != 0 ||
2600294332Sdes	    (r = sshbuf_reserve(m, slen, &p)) != 0)
2601294332Sdes		return r;
2602323134Sdes	if (cipher_get_keycontext(state->send_context, p) != (int)slen)
2603294332Sdes		return SSH_ERR_INTERNAL_ERROR;
2604294332Sdes	if ((r = sshbuf_put_u32(m, rlen)) != 0 ||
2605294332Sdes	    (r = sshbuf_reserve(m, rlen, &p)) != 0)
2606294332Sdes		return r;
2607323134Sdes	if (cipher_get_keycontext(state->receive_context, p) != (int)rlen)
2608294332Sdes		return SSH_ERR_INTERNAL_ERROR;
2609323134Sdes	if ((r = sshbuf_put_stringb(m, state->input)) != 0 ||
2610294332Sdes	    (r = sshbuf_put_stringb(m, state->output)) != 0)
2611294332Sdes		return r;
2612294332Sdes
2613294332Sdes	return 0;
2614294332Sdes}
2615294332Sdes
2616294332Sdes/* restore key exchange results from blob for packet state de-serialization */
2617294332Sdesstatic int
2618294332Sdesnewkeys_from_blob(struct sshbuf *m, struct ssh *ssh, int mode)
2619294332Sdes{
2620294332Sdes	struct sshbuf *b = NULL;
2621294332Sdes	struct sshcomp *comp;
2622294332Sdes	struct sshenc *enc;
2623294332Sdes	struct sshmac *mac;
2624294332Sdes	struct newkeys *newkey = NULL;
2625294332Sdes	size_t keylen, ivlen, maclen;
2626294332Sdes	int r;
2627294332Sdes
2628294332Sdes	if ((newkey = calloc(1, sizeof(*newkey))) == NULL) {
2629294332Sdes		r = SSH_ERR_ALLOC_FAIL;
2630294332Sdes		goto out;
2631294332Sdes	}
2632294332Sdes	if ((r = sshbuf_froms(m, &b)) != 0)
2633294332Sdes		goto out;
2634294332Sdes#ifdef DEBUG_PK
2635294332Sdes	sshbuf_dump(b, stderr);
2636294332Sdes#endif
2637294332Sdes	enc = &newkey->enc;
2638294332Sdes	mac = &newkey->mac;
2639294332Sdes	comp = &newkey->comp;
2640294332Sdes
2641294332Sdes	if ((r = sshbuf_get_cstring(b, &enc->name, NULL)) != 0 ||
2642294332Sdes	    (r = sshbuf_get(b, &enc->cipher, sizeof(enc->cipher))) != 0 ||
2643294332Sdes	    (r = sshbuf_get_u32(b, (u_int *)&enc->enabled)) != 0 ||
2644294332Sdes	    (r = sshbuf_get_u32(b, &enc->block_size)) != 0 ||
2645294332Sdes	    (r = sshbuf_get_string(b, &enc->key, &keylen)) != 0 ||
2646294332Sdes	    (r = sshbuf_get_string(b, &enc->iv, &ivlen)) != 0)
2647294332Sdes		goto out;
2648294332Sdes	if (cipher_authlen(enc->cipher) == 0) {
2649294332Sdes		if ((r = sshbuf_get_cstring(b, &mac->name, NULL)) != 0)
2650294332Sdes			goto out;
2651294332Sdes		if ((r = mac_setup(mac, mac->name)) != 0)
2652294332Sdes			goto out;
2653294332Sdes		if ((r = sshbuf_get_u32(b, (u_int *)&mac->enabled)) != 0 ||
2654294332Sdes		    (r = sshbuf_get_string(b, &mac->key, &maclen)) != 0)
2655294332Sdes			goto out;
2656294332Sdes		if (maclen > mac->key_len) {
2657294332Sdes			r = SSH_ERR_INVALID_FORMAT;
2658294332Sdes			goto out;
2659294332Sdes		}
2660294332Sdes		mac->key_len = maclen;
2661294332Sdes	}
2662294332Sdes	if ((r = sshbuf_get_u32(b, &comp->type)) != 0 ||
2663294332Sdes	    (r = sshbuf_get_cstring(b, &comp->name, NULL)) != 0)
2664294332Sdes		goto out;
2665294332Sdes	if (enc->name == NULL ||
2666294332Sdes	    cipher_by_name(enc->name) != enc->cipher) {
2667294332Sdes		r = SSH_ERR_INVALID_FORMAT;
2668294332Sdes		goto out;
2669294332Sdes	}
2670294332Sdes	if (sshbuf_len(b) != 0) {
2671294332Sdes		r = SSH_ERR_INVALID_FORMAT;
2672294332Sdes		goto out;
2673294332Sdes	}
2674294332Sdes	enc->key_len = keylen;
2675294332Sdes	enc->iv_len = ivlen;
2676294332Sdes	ssh->kex->newkeys[mode] = newkey;
2677294332Sdes	newkey = NULL;
2678294332Sdes	r = 0;
2679294332Sdes out:
2680296633Sdes	free(newkey);
2681296633Sdes	sshbuf_free(b);
2682294332Sdes	return r;
2683294332Sdes}
2684294332Sdes
2685294332Sdes/* restore kex from blob for packet state de-serialization */
2686294332Sdesstatic int
2687294332Sdeskex_from_blob(struct sshbuf *m, struct kex **kexp)
2688294332Sdes{
2689294332Sdes	struct kex *kex;
2690294332Sdes	int r;
2691294332Sdes
2692294332Sdes	if ((kex = calloc(1, sizeof(struct kex))) == NULL ||
2693294332Sdes	    (kex->my = sshbuf_new()) == NULL ||
2694294332Sdes	    (kex->peer = sshbuf_new()) == NULL) {
2695294332Sdes		r = SSH_ERR_ALLOC_FAIL;
2696294332Sdes		goto out;
2697294332Sdes	}
2698294332Sdes	if ((r = sshbuf_get_string(m, &kex->session_id, &kex->session_id_len)) != 0 ||
2699294332Sdes	    (r = sshbuf_get_u32(m, &kex->we_need)) != 0 ||
2700294332Sdes	    (r = sshbuf_get_u32(m, (u_int *)&kex->hostkey_type)) != 0 ||
2701294332Sdes	    (r = sshbuf_get_u32(m, &kex->kex_type)) != 0 ||
2702294332Sdes	    (r = sshbuf_get_stringb(m, kex->my)) != 0 ||
2703294332Sdes	    (r = sshbuf_get_stringb(m, kex->peer)) != 0 ||
2704294332Sdes	    (r = sshbuf_get_u32(m, &kex->flags)) != 0 ||
2705294332Sdes	    (r = sshbuf_get_cstring(m, &kex->client_version_string, NULL)) != 0 ||
2706294332Sdes	    (r = sshbuf_get_cstring(m, &kex->server_version_string, NULL)) != 0)
2707294332Sdes		goto out;
2708294332Sdes	kex->server = 1;
2709294332Sdes	kex->done = 1;
2710294332Sdes	r = 0;
2711294332Sdes out:
2712294332Sdes	if (r != 0 || kexp == NULL) {
2713294332Sdes		if (kex != NULL) {
2714296633Sdes			sshbuf_free(kex->my);
2715296633Sdes			sshbuf_free(kex->peer);
2716294332Sdes			free(kex);
2717294332Sdes		}
2718294332Sdes		if (kexp != NULL)
2719294332Sdes			*kexp = NULL;
2720294332Sdes	} else {
2721294332Sdes		*kexp = kex;
2722294332Sdes	}
2723294332Sdes	return r;
2724294332Sdes}
2725294332Sdes
2726294332Sdes/*
2727294332Sdes * Restore packet state from content of blob 'm' (de-serialization).
2728294332Sdes * Note that 'm' will be partially consumed on parsing or any other errors.
2729294332Sdes */
2730294332Sdesint
2731294332Sdesssh_packet_set_state(struct ssh *ssh, struct sshbuf *m)
2732294332Sdes{
2733294332Sdes	struct session_state *state = ssh->state;
2734294332Sdes	const u_char *ssh1key, *ivin, *ivout, *keyin, *keyout, *input, *output;
2735294332Sdes	size_t ssh1keylen, rlen, slen, ilen, olen;
2736294332Sdes	int r;
2737294332Sdes	u_int ssh1cipher = 0;
2738294332Sdes
2739294332Sdes	if (!compat20) {
2740294332Sdes		if ((r = sshbuf_get_u32(m, &state->remote_protocol_flags)) != 0 ||
2741294332Sdes		    (r = sshbuf_get_u32(m, &ssh1cipher)) != 0 ||
2742294332Sdes		    (r = sshbuf_get_string_direct(m, &ssh1key, &ssh1keylen)) != 0 ||
2743294332Sdes		    (r = sshbuf_get_string_direct(m, &ivout, &slen)) != 0 ||
2744294332Sdes		    (r = sshbuf_get_string_direct(m, &ivin, &rlen)) != 0)
2745294332Sdes			return r;
2746294332Sdes		if (ssh1cipher > INT_MAX)
2747294332Sdes			return SSH_ERR_KEY_UNKNOWN_CIPHER;
2748294332Sdes		ssh_packet_set_encryption_key(ssh, ssh1key, ssh1keylen,
2749294332Sdes		    (int)ssh1cipher);
2750323134Sdes		if (cipher_get_keyiv_len(state->send_context) != (int)slen ||
2751323134Sdes		    cipher_get_keyiv_len(state->receive_context) != (int)rlen)
2752294332Sdes			return SSH_ERR_INVALID_FORMAT;
2753323134Sdes		if ((r = cipher_set_keyiv(state->send_context, ivout)) != 0 ||
2754323134Sdes		    (r = cipher_set_keyiv(state->receive_context, ivin)) != 0)
2755294332Sdes			return r;
2756294332Sdes	} else {
2757294332Sdes		if ((r = kex_from_blob(m, &ssh->kex)) != 0 ||
2758294332Sdes		    (r = newkeys_from_blob(m, ssh, MODE_OUT)) != 0 ||
2759294332Sdes		    (r = newkeys_from_blob(m, ssh, MODE_IN)) != 0 ||
2760296633Sdes		    (r = sshbuf_get_u64(m, &state->rekey_limit)) != 0 ||
2761294332Sdes		    (r = sshbuf_get_u32(m, &state->rekey_interval)) != 0 ||
2762294332Sdes		    (r = sshbuf_get_u32(m, &state->p_send.seqnr)) != 0 ||
2763294332Sdes		    (r = sshbuf_get_u64(m, &state->p_send.blocks)) != 0 ||
2764294332Sdes		    (r = sshbuf_get_u32(m, &state->p_send.packets)) != 0 ||
2765294332Sdes		    (r = sshbuf_get_u64(m, &state->p_send.bytes)) != 0 ||
2766294332Sdes		    (r = sshbuf_get_u32(m, &state->p_read.seqnr)) != 0 ||
2767294332Sdes		    (r = sshbuf_get_u64(m, &state->p_read.blocks)) != 0 ||
2768294332Sdes		    (r = sshbuf_get_u32(m, &state->p_read.packets)) != 0 ||
2769294332Sdes		    (r = sshbuf_get_u64(m, &state->p_read.bytes)) != 0)
2770294332Sdes			return r;
2771294332Sdes		/*
2772294332Sdes		 * We set the time here so that in post-auth privsep slave we
2773294332Sdes		 * count from the completion of the authentication.
2774294332Sdes		 */
2775294332Sdes		state->rekey_time = monotime();
2776294332Sdes		/* XXX ssh_set_newkeys overrides p_read.packets? XXX */
2777294332Sdes		if ((r = ssh_set_newkeys(ssh, MODE_IN)) != 0 ||
2778294332Sdes		    (r = ssh_set_newkeys(ssh, MODE_OUT)) != 0)
2779294332Sdes			return r;
2780294332Sdes	}
2781294332Sdes	if ((r = sshbuf_get_string_direct(m, &keyout, &slen)) != 0 ||
2782294332Sdes	    (r = sshbuf_get_string_direct(m, &keyin, &rlen)) != 0)
2783294332Sdes		return r;
2784323134Sdes	if (cipher_get_keycontext(state->send_context, NULL) != (int)slen ||
2785323134Sdes	    cipher_get_keycontext(state->receive_context, NULL) != (int)rlen)
2786294332Sdes		return SSH_ERR_INVALID_FORMAT;
2787323134Sdes	cipher_set_keycontext(state->send_context, keyout);
2788323134Sdes	cipher_set_keycontext(state->receive_context, keyin);
2789294332Sdes
2790323134Sdes	if ((r = ssh_packet_set_postauth(ssh)) != 0)
2791294332Sdes		return r;
2792294332Sdes
2793294332Sdes	sshbuf_reset(state->input);
2794294332Sdes	sshbuf_reset(state->output);
2795294332Sdes	if ((r = sshbuf_get_string_direct(m, &input, &ilen)) != 0 ||
2796294332Sdes	    (r = sshbuf_get_string_direct(m, &output, &olen)) != 0 ||
2797294332Sdes	    (r = sshbuf_put(state->input, input, ilen)) != 0 ||
2798294332Sdes	    (r = sshbuf_put(state->output, output, olen)) != 0)
2799294332Sdes		return r;
2800294332Sdes
2801294332Sdes	if (sshbuf_len(m))
2802294332Sdes		return SSH_ERR_INVALID_FORMAT;
2803294332Sdes	debug3("%s: done", __func__);
2804294332Sdes	return 0;
2805294332Sdes}
2806294332Sdes
2807294332Sdes/* NEW API */
2808294332Sdes
2809294332Sdes/* put data to the outgoing packet */
2810294332Sdes
2811294332Sdesint
2812294332Sdessshpkt_put(struct ssh *ssh, const void *v, size_t len)
2813294332Sdes{
2814294332Sdes	return sshbuf_put(ssh->state->outgoing_packet, v, len);
2815294332Sdes}
2816294332Sdes
2817294332Sdesint
2818294332Sdessshpkt_putb(struct ssh *ssh, const struct sshbuf *b)
2819294332Sdes{
2820294332Sdes	return sshbuf_putb(ssh->state->outgoing_packet, b);
2821294332Sdes}
2822294332Sdes
2823294332Sdesint
2824294332Sdessshpkt_put_u8(struct ssh *ssh, u_char val)
2825294332Sdes{
2826294332Sdes	return sshbuf_put_u8(ssh->state->outgoing_packet, val);
2827294332Sdes}
2828294332Sdes
2829294332Sdesint
2830294332Sdessshpkt_put_u32(struct ssh *ssh, u_int32_t val)
2831294332Sdes{
2832294332Sdes	return sshbuf_put_u32(ssh->state->outgoing_packet, val);
2833294332Sdes}
2834294332Sdes
2835294332Sdesint
2836294332Sdessshpkt_put_u64(struct ssh *ssh, u_int64_t val)
2837294332Sdes{
2838294332Sdes	return sshbuf_put_u64(ssh->state->outgoing_packet, val);
2839294332Sdes}
2840294332Sdes
2841294332Sdesint
2842294332Sdessshpkt_put_string(struct ssh *ssh, const void *v, size_t len)
2843294332Sdes{
2844294332Sdes	return sshbuf_put_string(ssh->state->outgoing_packet, v, len);
2845294332Sdes}
2846294332Sdes
2847294332Sdesint
2848294332Sdessshpkt_put_cstring(struct ssh *ssh, const void *v)
2849294332Sdes{
2850294332Sdes	return sshbuf_put_cstring(ssh->state->outgoing_packet, v);
2851294332Sdes}
2852294332Sdes
2853294332Sdesint
2854294332Sdessshpkt_put_stringb(struct ssh *ssh, const struct sshbuf *v)
2855294332Sdes{
2856294332Sdes	return sshbuf_put_stringb(ssh->state->outgoing_packet, v);
2857294332Sdes}
2858294332Sdes
2859294336Sdes#ifdef WITH_OPENSSL
2860294336Sdes#ifdef OPENSSL_HAS_ECC
2861294332Sdesint
2862294332Sdessshpkt_put_ec(struct ssh *ssh, const EC_POINT *v, const EC_GROUP *g)
2863294332Sdes{
2864294332Sdes	return sshbuf_put_ec(ssh->state->outgoing_packet, v, g);
2865294332Sdes}
2866294336Sdes#endif /* OPENSSL_HAS_ECC */
2867294332Sdes
2868294332Sdes#ifdef WITH_SSH1
2869294332Sdesint
2870294332Sdessshpkt_put_bignum1(struct ssh *ssh, const BIGNUM *v)
2871294332Sdes{
2872294332Sdes	return sshbuf_put_bignum1(ssh->state->outgoing_packet, v);
2873294332Sdes}
2874294332Sdes#endif /* WITH_SSH1 */
2875294332Sdes
2876294332Sdesint
2877294332Sdessshpkt_put_bignum2(struct ssh *ssh, const BIGNUM *v)
2878294332Sdes{
2879294332Sdes	return sshbuf_put_bignum2(ssh->state->outgoing_packet, v);
2880294332Sdes}
2881294332Sdes#endif /* WITH_OPENSSL */
2882294332Sdes
2883294332Sdes/* fetch data from the incoming packet */
2884294332Sdes
2885294332Sdesint
2886294332Sdessshpkt_get(struct ssh *ssh, void *valp, size_t len)
2887294332Sdes{
2888294332Sdes	return sshbuf_get(ssh->state->incoming_packet, valp, len);
2889294332Sdes}
2890294332Sdes
2891294332Sdesint
2892294332Sdessshpkt_get_u8(struct ssh *ssh, u_char *valp)
2893294332Sdes{
2894294332Sdes	return sshbuf_get_u8(ssh->state->incoming_packet, valp);
2895294332Sdes}
2896294332Sdes
2897294332Sdesint
2898294332Sdessshpkt_get_u32(struct ssh *ssh, u_int32_t *valp)
2899294332Sdes{
2900294332Sdes	return sshbuf_get_u32(ssh->state->incoming_packet, valp);
2901294332Sdes}
2902294332Sdes
2903294332Sdesint
2904294332Sdessshpkt_get_u64(struct ssh *ssh, u_int64_t *valp)
2905294332Sdes{
2906294332Sdes	return sshbuf_get_u64(ssh->state->incoming_packet, valp);
2907294332Sdes}
2908294332Sdes
2909294332Sdesint
2910294332Sdessshpkt_get_string(struct ssh *ssh, u_char **valp, size_t *lenp)
2911294332Sdes{
2912294332Sdes	return sshbuf_get_string(ssh->state->incoming_packet, valp, lenp);
2913294332Sdes}
2914294332Sdes
2915294332Sdesint
2916294332Sdessshpkt_get_string_direct(struct ssh *ssh, const u_char **valp, size_t *lenp)
2917294332Sdes{
2918294332Sdes	return sshbuf_get_string_direct(ssh->state->incoming_packet, valp, lenp);
2919294332Sdes}
2920294332Sdes
2921294332Sdesint
2922294332Sdessshpkt_get_cstring(struct ssh *ssh, char **valp, size_t *lenp)
2923294332Sdes{
2924294332Sdes	return sshbuf_get_cstring(ssh->state->incoming_packet, valp, lenp);
2925294332Sdes}
2926294332Sdes
2927294336Sdes#ifdef WITH_OPENSSL
2928294336Sdes#ifdef OPENSSL_HAS_ECC
2929294332Sdesint
2930294332Sdessshpkt_get_ec(struct ssh *ssh, EC_POINT *v, const EC_GROUP *g)
2931294332Sdes{
2932294332Sdes	return sshbuf_get_ec(ssh->state->incoming_packet, v, g);
2933294332Sdes}
2934294336Sdes#endif /* OPENSSL_HAS_ECC */
2935294332Sdes
2936294332Sdes#ifdef WITH_SSH1
2937294332Sdesint
2938294332Sdessshpkt_get_bignum1(struct ssh *ssh, BIGNUM *v)
2939294332Sdes{
2940294332Sdes	return sshbuf_get_bignum1(ssh->state->incoming_packet, v);
2941294332Sdes}
2942294332Sdes#endif /* WITH_SSH1 */
2943294332Sdes
2944294332Sdesint
2945294332Sdessshpkt_get_bignum2(struct ssh *ssh, BIGNUM *v)
2946294332Sdes{
2947294332Sdes	return sshbuf_get_bignum2(ssh->state->incoming_packet, v);
2948294332Sdes}
2949294332Sdes#endif /* WITH_OPENSSL */
2950294332Sdes
2951294332Sdesint
2952294332Sdessshpkt_get_end(struct ssh *ssh)
2953294332Sdes{
2954294332Sdes	if (sshbuf_len(ssh->state->incoming_packet) > 0)
2955294332Sdes		return SSH_ERR_UNEXPECTED_TRAILING_DATA;
2956294332Sdes	return 0;
2957294332Sdes}
2958294332Sdes
2959294332Sdesconst u_char *
2960294332Sdessshpkt_ptr(struct ssh *ssh, size_t *lenp)
2961294332Sdes{
2962294332Sdes	if (lenp != NULL)
2963294332Sdes		*lenp = sshbuf_len(ssh->state->incoming_packet);
2964294332Sdes	return sshbuf_ptr(ssh->state->incoming_packet);
2965294332Sdes}
2966294332Sdes
2967294332Sdes/* start a new packet */
2968294332Sdes
2969294332Sdesint
2970294332Sdessshpkt_start(struct ssh *ssh, u_char type)
2971294332Sdes{
2972294332Sdes	u_char buf[9];
2973294332Sdes	int len;
2974294332Sdes
2975294332Sdes	DBG(debug("packet_start[%d]", type));
2976294332Sdes	len = compat20 ? 6 : 9;
2977294332Sdes	memset(buf, 0, len - 1);
2978294332Sdes	buf[len - 1] = type;
2979294332Sdes	sshbuf_reset(ssh->state->outgoing_packet);
2980294332Sdes	return sshbuf_put(ssh->state->outgoing_packet, buf, len);
2981294332Sdes}
2982294332Sdes
2983323134Sdesstatic int
2984323134Sdesssh_packet_send_mux(struct ssh *ssh)
2985323134Sdes{
2986323134Sdes	struct session_state *state = ssh->state;
2987323134Sdes	u_char type, *cp;
2988323134Sdes	size_t len;
2989323134Sdes	int r;
2990323134Sdes
2991323134Sdes	if (ssh->kex)
2992323134Sdes		return SSH_ERR_INTERNAL_ERROR;
2993323134Sdes	len = sshbuf_len(state->outgoing_packet);
2994323134Sdes	if (len < 6)
2995323134Sdes		return SSH_ERR_INTERNAL_ERROR;
2996323134Sdes	cp = sshbuf_mutable_ptr(state->outgoing_packet);
2997323134Sdes	type = cp[5];
2998323134Sdes	if (ssh_packet_log_type(type))
2999323134Sdes		debug3("%s: type %u", __func__, type);
3000323134Sdes	/* drop everything, but the connection protocol */
3001323134Sdes	if (type >= SSH2_MSG_CONNECTION_MIN &&
3002323134Sdes	    type <= SSH2_MSG_CONNECTION_MAX) {
3003323134Sdes		POKE_U32(cp, len - 4);
3004323134Sdes		if ((r = sshbuf_putb(state->output,
3005323134Sdes		    state->outgoing_packet)) != 0)
3006323134Sdes			return r;
3007323134Sdes		/* sshbuf_dump(state->output, stderr); */
3008323134Sdes	}
3009323134Sdes	sshbuf_reset(state->outgoing_packet);
3010323134Sdes	return 0;
3011323134Sdes}
3012323134Sdes
3013294332Sdes/* send it */
3014294332Sdes
3015294332Sdesint
3016294332Sdessshpkt_send(struct ssh *ssh)
3017294332Sdes{
3018323134Sdes	if (ssh->state && ssh->state->mux)
3019323134Sdes		return ssh_packet_send_mux(ssh);
3020294332Sdes	if (compat20)
3021294332Sdes		return ssh_packet_send2(ssh);
3022294332Sdes	else
3023294332Sdes		return ssh_packet_send1(ssh);
3024294332Sdes}
3025294332Sdes
3026294332Sdesint
3027294332Sdessshpkt_disconnect(struct ssh *ssh, const char *fmt,...)
3028294332Sdes{
3029294332Sdes	char buf[1024];
3030294332Sdes	va_list args;
3031294332Sdes	int r;
3032294332Sdes
3033294332Sdes	va_start(args, fmt);
3034294332Sdes	vsnprintf(buf, sizeof(buf), fmt, args);
3035294332Sdes	va_end(args);
3036294332Sdes
3037294332Sdes	if (compat20) {
3038294332Sdes		if ((r = sshpkt_start(ssh, SSH2_MSG_DISCONNECT)) != 0 ||
3039294332Sdes		    (r = sshpkt_put_u32(ssh, SSH2_DISCONNECT_PROTOCOL_ERROR)) != 0 ||
3040294332Sdes		    (r = sshpkt_put_cstring(ssh, buf)) != 0 ||
3041294332Sdes		    (r = sshpkt_put_cstring(ssh, "")) != 0 ||
3042294332Sdes		    (r = sshpkt_send(ssh)) != 0)
3043294332Sdes			return r;
3044294332Sdes	} else {
3045294332Sdes		if ((r = sshpkt_start(ssh, SSH_MSG_DISCONNECT)) != 0 ||
3046294332Sdes		    (r = sshpkt_put_cstring(ssh, buf)) != 0 ||
3047294332Sdes		    (r = sshpkt_send(ssh)) != 0)
3048294332Sdes			return r;
3049294332Sdes	}
3050294332Sdes	return 0;
3051294332Sdes}
3052294332Sdes
3053294332Sdes/* roundup current message to pad bytes */
3054294332Sdesint
3055294332Sdessshpkt_add_padding(struct ssh *ssh, u_char pad)
3056294332Sdes{
3057294332Sdes	ssh->state->extra_pad = pad;
3058294332Sdes	return 0;
3059294332Sdes}
3060