packet.c revision 181111
1181111Sdes/* $OpenBSD: packet.c,v 1.157 2008/07/10 18:08:11 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"
41162852Sdes
42162852Sdes#include <sys/types.h>
43124208Sdes#include "openbsd-compat/sys-queue.h"
44162852Sdes#include <sys/param.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>
55162852Sdes#include <stdarg.h>
56162852Sdes#include <stdio.h>
57162852Sdes#include <stdlib.h>
58162852Sdes#include <string.h>
59162852Sdes#include <unistd.h>
60162852Sdes#include <signal.h>
61162852Sdes
6257429Smarkm#include "xmalloc.h"
6357429Smarkm#include "buffer.h"
6457429Smarkm#include "packet.h"
6557429Smarkm#include "crc32.h"
6657429Smarkm#include "compress.h"
6757429Smarkm#include "deattack.h"
6860573Skris#include "channels.h"
6960573Skris#include "compat.h"
7076259Sgreen#include "ssh1.h"
7160573Skris#include "ssh2.h"
7269587Sgreen#include "cipher.h"
73162852Sdes#include "key.h"
7460573Skris#include "kex.h"
7576259Sgreen#include "mac.h"
7676259Sgreen#include "log.h"
7776259Sgreen#include "canohost.h"
7892555Sdes#include "misc.h"
7998675Sdes#include "ssh.h"
8060573Skris
8160573Skris#ifdef PACKET_DEBUG
8260573Skris#define DBG(x) x
8360573Skris#else
8460573Skris#define DBG(x)
8560573Skris#endif
8660573Skris
8757429Smarkm/*
8857429Smarkm * This variable contains the file descriptors used for communicating with
8957429Smarkm * the other side.  connection_in is used for reading; connection_out for
9057429Smarkm * writing.  These can be the same descriptor, in which case it is assumed to
9157429Smarkm * be a socket.
9257429Smarkm */
9357429Smarkmstatic int connection_in = -1;
9457429Smarkmstatic int connection_out = -1;
9557429Smarkm
9657429Smarkm/* Protocol flags for the remote side. */
9776259Sgreenstatic u_int remote_protocol_flags = 0;
9857429Smarkm
9957429Smarkm/* Encryption context for receiving data.  This is only used for decryption. */
10057429Smarkmstatic CipherContext receive_context;
10157429Smarkm
10257429Smarkm/* Encryption context for sending data.  This is only used for encryption. */
10357429Smarkmstatic CipherContext send_context;
10457429Smarkm
10557429Smarkm/* Buffer for raw input data from the socket. */
10698675SdesBuffer input;
10757429Smarkm
10857429Smarkm/* Buffer for raw output data going to the socket. */
10998675SdesBuffer output;
11057429Smarkm
11157429Smarkm/* Buffer for the partial outgoing packet being constructed. */
11257429Smarkmstatic Buffer outgoing_packet;
11357429Smarkm
11457429Smarkm/* Buffer for the incoming packet currently being processed. */
11557429Smarkmstatic Buffer incoming_packet;
11657429Smarkm
11757429Smarkm/* Scratch buffer for packet compression/decompression. */
11857429Smarkmstatic Buffer compression_buffer;
11976259Sgreenstatic int compression_buffer_ready = 0;
12057429Smarkm
12157429Smarkm/* Flag indicating whether packet compression/decompression is enabled. */
12257429Smarkmstatic int packet_compression = 0;
12357429Smarkm
12457429Smarkm/* default maximum packet size */
125124208Sdesu_int max_packet_size = 32768;
12657429Smarkm
12757429Smarkm/* Flag indicating whether this module has been initialized. */
12857429Smarkmstatic int initialized = 0;
12957429Smarkm
13057429Smarkm/* Set to true if the connection is interactive. */
13157429Smarkmstatic int interactive_mode = 0;
13257429Smarkm
133149749Sdes/* Set to true if we are the server side. */
134149749Sdesstatic int server_side = 0;
135149749Sdes
136149749Sdes/* Set to true if we are authenticated. */
137149749Sdesstatic int after_authentication = 0;
138149749Sdes
139181111Sdesint keep_alive_timeouts = 0;
140181111Sdes
141181111Sdes/* Set to the maximum time that we will wait to send or receive a packet */
142181111Sdesstatic int packet_timeout_ms = -1;
143181111Sdes
14460573Skris/* Session key information for Encryption and MAC */
14576259SgreenNewkeys *newkeys[MODE_MAX];
146124208Sdesstatic struct packet_state {
147124208Sdes	u_int32_t seqnr;
148124208Sdes	u_int32_t packets;
149124208Sdes	u_int64_t blocks;
150181111Sdes	u_int64_t bytes;
151124208Sdes} p_read, p_send;
15260573Skris
153124208Sdesstatic u_int64_t max_blocks_in, max_blocks_out;
154124208Sdesstatic u_int32_t rekey_limit;
155124208Sdes
15698675Sdes/* Session key for protocol v1 */
15798675Sdesstatic u_char ssh1_key[SSH_SESSION_KEY_LENGTH];
15898675Sdesstatic u_int ssh1_keylen;
15998675Sdes
16092555Sdes/* roundup current message to extra_pad bytes */
16192555Sdesstatic u_char extra_pad = 0;
16260573Skris
163124208Sdesstruct packet {
164124208Sdes	TAILQ_ENTRY(packet) next;
165124208Sdes	u_char type;
166124208Sdes	Buffer payload;
167124208Sdes};
168124208SdesTAILQ_HEAD(, packet) outgoing;
169124208Sdes
17057429Smarkm/*
17157429Smarkm * Sets the descriptors used for communication.  Disables encryption until
17257429Smarkm * packet_set_encryption_key is called.
17357429Smarkm */
17457429Smarkmvoid
17557429Smarkmpacket_set_connection(int fd_in, int fd_out)
17657429Smarkm{
17769587Sgreen	Cipher *none = cipher_by_name("none");
178106121Sdes
17969587Sgreen	if (none == NULL)
18069587Sgreen		fatal("packet_set_connection: cannot load cipher 'none'");
18157429Smarkm	connection_in = fd_in;
18257429Smarkm	connection_out = fd_out;
183137015Sdes	cipher_init(&send_context, none, (const u_char *)"",
184137015Sdes	    0, NULL, 0, CIPHER_ENCRYPT);
185137015Sdes	cipher_init(&receive_context, none, (const u_char *)"",
186137015Sdes	    0, NULL, 0, CIPHER_DECRYPT);
18792555Sdes	newkeys[MODE_IN] = newkeys[MODE_OUT] = NULL;
18857429Smarkm	if (!initialized) {
18957429Smarkm		initialized = 1;
19057429Smarkm		buffer_init(&input);
19157429Smarkm		buffer_init(&output);
19257429Smarkm		buffer_init(&outgoing_packet);
19357429Smarkm		buffer_init(&incoming_packet);
194124208Sdes		TAILQ_INIT(&outgoing);
195181111Sdes		p_send.packets = p_read.packets = 0;
19657429Smarkm	}
19757429Smarkm}
19857429Smarkm
199181111Sdesvoid
200181111Sdespacket_set_timeout(int timeout, int count)
201181111Sdes{
202181111Sdes	if (timeout == 0 || count == 0) {
203181111Sdes		packet_timeout_ms = -1;
204181111Sdes		return;
205181111Sdes	}
206181111Sdes	if ((INT_MAX / 1000) / count < timeout)
207181111Sdes		packet_timeout_ms = INT_MAX;
208181111Sdes	else
209181111Sdes		packet_timeout_ms = timeout * count * 1000;
210181111Sdes}
211181111Sdes
21257429Smarkm/* Returns 1 if remote host is connected via socket, 0 if not. */
21357429Smarkm
21457429Smarkmint
21592555Sdespacket_connection_is_on_socket(void)
21657429Smarkm{
21757429Smarkm	struct sockaddr_storage from, to;
21857429Smarkm	socklen_t fromlen, tolen;
21957429Smarkm
22057429Smarkm	/* filedescriptors in and out are the same, so it's a socket */
22157429Smarkm	if (connection_in == connection_out)
22257429Smarkm		return 1;
22357429Smarkm	fromlen = sizeof(from);
22457429Smarkm	memset(&from, 0, sizeof(from));
22557429Smarkm	if (getpeername(connection_in, (struct sockaddr *)&from, &fromlen) < 0)
22657429Smarkm		return 0;
22757429Smarkm	tolen = sizeof(to);
22857429Smarkm	memset(&to, 0, sizeof(to));
22957429Smarkm	if (getpeername(connection_out, (struct sockaddr *)&to, &tolen) < 0)
23057429Smarkm		return 0;
23157429Smarkm	if (fromlen != tolen || memcmp(&from, &to, fromlen) != 0)
23257429Smarkm		return 0;
23357429Smarkm	if (from.ss_family != AF_INET && from.ss_family != AF_INET6)
23457429Smarkm		return 0;
23557429Smarkm	return 1;
23657429Smarkm}
23757429Smarkm
23898675Sdes/*
23998675Sdes * Exports an IV from the CipherContext required to export the key
24098675Sdes * state back from the unprivileged child to the privileged parent
24198675Sdes * process.
24298675Sdes */
24398675Sdes
24498675Sdesvoid
24598675Sdespacket_get_keyiv(int mode, u_char *iv, u_int len)
24698675Sdes{
24798675Sdes	CipherContext *cc;
24898675Sdes
24998675Sdes	if (mode == MODE_OUT)
25098675Sdes		cc = &send_context;
25198675Sdes	else
25298675Sdes		cc = &receive_context;
25398675Sdes
25498675Sdes	cipher_get_keyiv(cc, iv, len);
25598675Sdes}
25698675Sdes
25798675Sdesint
25898675Sdespacket_get_keycontext(int mode, u_char *dat)
25998675Sdes{
26098675Sdes	CipherContext *cc;
26198675Sdes
26298675Sdes	if (mode == MODE_OUT)
26398675Sdes		cc = &send_context;
26498675Sdes	else
26598675Sdes		cc = &receive_context;
26698675Sdes
26798675Sdes	return (cipher_get_keycontext(cc, dat));
26898675Sdes}
26998675Sdes
27098675Sdesvoid
27198675Sdespacket_set_keycontext(int mode, u_char *dat)
27298675Sdes{
27398675Sdes	CipherContext *cc;
27498675Sdes
27598675Sdes	if (mode == MODE_OUT)
27698675Sdes		cc = &send_context;
27798675Sdes	else
27898675Sdes		cc = &receive_context;
27998675Sdes
28098675Sdes	cipher_set_keycontext(cc, dat);
28198675Sdes}
28298675Sdes
28398675Sdesint
28498675Sdespacket_get_keyiv_len(int mode)
28598675Sdes{
28698675Sdes	CipherContext *cc;
28798675Sdes
28898675Sdes	if (mode == MODE_OUT)
28998675Sdes		cc = &send_context;
29098675Sdes	else
29198675Sdes		cc = &receive_context;
29298675Sdes
29398675Sdes	return (cipher_get_keyiv_len(cc));
29498675Sdes}
295162852Sdes
29698675Sdesvoid
29798675Sdespacket_set_iv(int mode, u_char *dat)
29898675Sdes{
29998675Sdes	CipherContext *cc;
30098675Sdes
30198675Sdes	if (mode == MODE_OUT)
30298675Sdes		cc = &send_context;
30398675Sdes	else
30498675Sdes		cc = &receive_context;
30598675Sdes
30698675Sdes	cipher_set_keyiv(cc, dat);
30798675Sdes}
308162852Sdes
30998675Sdesint
310124208Sdespacket_get_ssh1_cipher(void)
31198675Sdes{
31298675Sdes	return (cipher_get_number(receive_context.cipher));
31398675Sdes}
31498675Sdes
315124208Sdesvoid
316181111Sdespacket_get_state(int mode, u_int32_t *seqnr, u_int64_t *blocks, u_int32_t *packets,
317181111Sdes    u_int64_t *bytes)
318124208Sdes{
319124208Sdes	struct packet_state *state;
32098675Sdes
321124208Sdes	state = (mode == MODE_IN) ? &p_read : &p_send;
322181111Sdes	if (seqnr)
323181111Sdes		*seqnr = state->seqnr;
324181111Sdes	if (blocks)
325181111Sdes		*blocks = state->blocks;
326181111Sdes	if (packets)
327181111Sdes		*packets = state->packets;
328181111Sdes	if (bytes)
329181111Sdes		*bytes = state->bytes;
33098675Sdes}
33198675Sdes
33298675Sdesvoid
333181111Sdespacket_set_state(int mode, u_int32_t seqnr, u_int64_t blocks, u_int32_t packets,
334181111Sdes    u_int64_t bytes)
33598675Sdes{
336124208Sdes	struct packet_state *state;
337124208Sdes
338124208Sdes	state = (mode == MODE_IN) ? &p_read : &p_send;
339124208Sdes	state->seqnr = seqnr;
340124208Sdes	state->blocks = blocks;
341124208Sdes	state->packets = packets;
342181111Sdes	state->bytes = bytes;
34398675Sdes}
34498675Sdes
34557429Smarkm/* returns 1 if connection is via ipv4 */
34657429Smarkm
34757429Smarkmint
34892555Sdespacket_connection_is_ipv4(void)
34957429Smarkm{
35057429Smarkm	struct sockaddr_storage to;
35157429Smarkm	socklen_t tolen = sizeof(to);
35257429Smarkm
35357429Smarkm	memset(&to, 0, sizeof(to));
35457429Smarkm	if (getsockname(connection_out, (struct sockaddr *)&to, &tolen) < 0)
35557429Smarkm		return 0;
35698937Sdes	if (to.ss_family == AF_INET)
35798937Sdes		return 1;
35898937Sdes#ifdef IPV4_IN_IPV6
359126274Sdes	if (to.ss_family == AF_INET6 &&
36098937Sdes	    IN6_IS_ADDR_V4MAPPED(&((struct sockaddr_in6 *)&to)->sin6_addr))
36198937Sdes		return 1;
36298937Sdes#endif
36398937Sdes	return 0;
36457429Smarkm}
36557429Smarkm
36657429Smarkm/* Sets the connection into non-blocking mode. */
36757429Smarkm
36857429Smarkmvoid
36992555Sdespacket_set_nonblocking(void)
37057429Smarkm{
37157429Smarkm	/* Set the socket into non-blocking mode. */
372137015Sdes	set_nonblock(connection_in);
37357429Smarkm
374137015Sdes	if (connection_out != connection_in)
375137015Sdes		set_nonblock(connection_out);
37657429Smarkm}
37757429Smarkm
37857429Smarkm/* Returns the socket used for reading. */
37957429Smarkm
38057429Smarkmint
38192555Sdespacket_get_connection_in(void)
38257429Smarkm{
38357429Smarkm	return connection_in;
38457429Smarkm}
38557429Smarkm
38657429Smarkm/* Returns the descriptor used for writing. */
38757429Smarkm
38857429Smarkmint
38992555Sdespacket_get_connection_out(void)
39057429Smarkm{
39157429Smarkm	return connection_out;
39257429Smarkm}
39357429Smarkm
39457429Smarkm/* Closes the connection and clears and frees internal data structures. */
39557429Smarkm
39657429Smarkmvoid
39792555Sdespacket_close(void)
39857429Smarkm{
39957429Smarkm	if (!initialized)
40057429Smarkm		return;
40157429Smarkm	initialized = 0;
40257429Smarkm	if (connection_in == connection_out) {
40357429Smarkm		shutdown(connection_out, SHUT_RDWR);
40457429Smarkm		close(connection_out);
40557429Smarkm	} else {
40657429Smarkm		close(connection_in);
40757429Smarkm		close(connection_out);
40857429Smarkm	}
40957429Smarkm	buffer_free(&input);
41057429Smarkm	buffer_free(&output);
41157429Smarkm	buffer_free(&outgoing_packet);
41257429Smarkm	buffer_free(&incoming_packet);
41376259Sgreen	if (compression_buffer_ready) {
41457429Smarkm		buffer_free(&compression_buffer);
41557429Smarkm		buffer_compress_uninit();
41657429Smarkm	}
41792555Sdes	cipher_cleanup(&send_context);
41892555Sdes	cipher_cleanup(&receive_context);
41957429Smarkm}
42057429Smarkm
42157429Smarkm/* Sets remote side protocol flags. */
42257429Smarkm
42357429Smarkmvoid
42476259Sgreenpacket_set_protocol_flags(u_int protocol_flags)
42557429Smarkm{
42657429Smarkm	remote_protocol_flags = protocol_flags;
42757429Smarkm}
42857429Smarkm
42957429Smarkm/* Returns the remote protocol flags set earlier by the above function. */
43057429Smarkm
43176259Sgreenu_int
43292555Sdespacket_get_protocol_flags(void)
43357429Smarkm{
43457429Smarkm	return remote_protocol_flags;
43557429Smarkm}
43657429Smarkm
43757429Smarkm/*
43857429Smarkm * Starts packet compression from the next packet on in both directions.
43957429Smarkm * Level is compression level 1 (fastest) - 9 (slow, best) as in gzip.
44057429Smarkm */
44157429Smarkm
44292555Sdesstatic void
44392555Sdespacket_init_compression(void)
44476259Sgreen{
44576259Sgreen	if (compression_buffer_ready == 1)
44676259Sgreen		return;
44776259Sgreen	compression_buffer_ready = 1;
44876259Sgreen	buffer_init(&compression_buffer);
44976259Sgreen}
45076259Sgreen
45176259Sgreenvoid
45257429Smarkmpacket_start_compression(int level)
45357429Smarkm{
45492555Sdes	if (packet_compression && !compat20)
45557429Smarkm		fatal("Compression already enabled.");
45657429Smarkm	packet_compression = 1;
45776259Sgreen	packet_init_compression();
45876259Sgreen	buffer_compress_init_send(level);
45976259Sgreen	buffer_compress_init_recv();
46057429Smarkm}
46157429Smarkm
46257429Smarkm/*
46357429Smarkm * Causes any further packets to be encrypted using the given key.  The same
46457429Smarkm * key is used for both sending and reception.  However, both directions are
46557429Smarkm * encrypted independently of each other.
46657429Smarkm */
46798675Sdes
46857429Smarkmvoid
46976259Sgreenpacket_set_encryption_key(const u_char *key, u_int keylen,
47069587Sgreen    int number)
47157429Smarkm{
47269587Sgreen	Cipher *cipher = cipher_by_number(number);
473106121Sdes
47469587Sgreen	if (cipher == NULL)
47569587Sgreen		fatal("packet_set_encryption_key: unknown cipher number %d", number);
47660573Skris	if (keylen < 20)
47769587Sgreen		fatal("packet_set_encryption_key: keylen too small: %d", keylen);
47898675Sdes	if (keylen > SSH_SESSION_KEY_LENGTH)
47998675Sdes		fatal("packet_set_encryption_key: keylen too big: %d", keylen);
48098675Sdes	memcpy(ssh1_key, key, keylen);
48198675Sdes	ssh1_keylen = keylen;
48292555Sdes	cipher_init(&send_context, cipher, key, keylen, NULL, 0, CIPHER_ENCRYPT);
48392555Sdes	cipher_init(&receive_context, cipher, key, keylen, NULL, 0, CIPHER_DECRYPT);
48457429Smarkm}
48557429Smarkm
48698675Sdesu_int
48798675Sdespacket_get_encryption_key(u_char *key)
48898675Sdes{
48998675Sdes	if (key == NULL)
49098675Sdes		return (ssh1_keylen);
49198675Sdes	memcpy(key, ssh1_key, ssh1_keylen);
49298675Sdes	return (ssh1_keylen);
49398675Sdes}
49498675Sdes
49592555Sdes/* Start constructing a packet to send. */
49657429Smarkmvoid
49792555Sdespacket_start(u_char type)
49857429Smarkm{
49992555Sdes	u_char buf[9];
50092555Sdes	int len;
50157429Smarkm
50292555Sdes	DBG(debug("packet_start[%d]", type));
50392555Sdes	len = compat20 ? 6 : 9;
50492555Sdes	memset(buf, 0, len - 1);
50592555Sdes	buf[len - 1] = type;
50657429Smarkm	buffer_clear(&outgoing_packet);
50792555Sdes	buffer_append(&outgoing_packet, buf, len);
50857429Smarkm}
50957429Smarkm
51092555Sdes/* Append payload. */
51160573Skrisvoid
51257429Smarkmpacket_put_char(int value)
51357429Smarkm{
51457429Smarkm	char ch = value;
515106121Sdes
51657429Smarkm	buffer_append(&outgoing_packet, &ch, 1);
51757429Smarkm}
518162852Sdes
51957429Smarkmvoid
52076259Sgreenpacket_put_int(u_int value)
52157429Smarkm{
52257429Smarkm	buffer_put_int(&outgoing_packet, value);
52357429Smarkm}
524162852Sdes
52557429Smarkmvoid
52692555Sdespacket_put_string(const void *buf, u_int len)
52757429Smarkm{
52857429Smarkm	buffer_put_string(&outgoing_packet, buf, len);
52957429Smarkm}
530162852Sdes
53160573Skrisvoid
53260573Skrispacket_put_cstring(const char *str)
53360573Skris{
53492555Sdes	buffer_put_cstring(&outgoing_packet, str);
53560573Skris}
536162852Sdes
53760573Skrisvoid
53892555Sdespacket_put_raw(const void *buf, u_int len)
53960573Skris{
54060573Skris	buffer_append(&outgoing_packet, buf, len);
54160573Skris}
542162852Sdes
54357429Smarkmvoid
54457429Smarkmpacket_put_bignum(BIGNUM * value)
54557429Smarkm{
54657429Smarkm	buffer_put_bignum(&outgoing_packet, value);
54757429Smarkm}
548162852Sdes
54960573Skrisvoid
55060573Skrispacket_put_bignum2(BIGNUM * value)
55160573Skris{
55260573Skris	buffer_put_bignum2(&outgoing_packet, value);
55360573Skris}
55457429Smarkm
55557429Smarkm/*
55657429Smarkm * Finalizes and sends the packet.  If the encryption key has been set,
55757429Smarkm * encrypts the packet before sending.
55857429Smarkm */
55957429Smarkm
56092555Sdesstatic void
56176259Sgreenpacket_send1(void)
56257429Smarkm{
56392555Sdes	u_char buf[8], *cp;
56457429Smarkm	int i, padding, len;
56576259Sgreen	u_int checksum;
566137015Sdes	u_int32_t rnd = 0;
56757429Smarkm
56857429Smarkm	/*
56957429Smarkm	 * If using packet compression, compress the payload of the outgoing
57057429Smarkm	 * packet.
57157429Smarkm	 */
57257429Smarkm	if (packet_compression) {
57357429Smarkm		buffer_clear(&compression_buffer);
57457429Smarkm		/* Skip padding. */
57557429Smarkm		buffer_consume(&outgoing_packet, 8);
57657429Smarkm		/* padding */
57757429Smarkm		buffer_append(&compression_buffer, "\0\0\0\0\0\0\0\0", 8);
57857429Smarkm		buffer_compress(&outgoing_packet, &compression_buffer);
57957429Smarkm		buffer_clear(&outgoing_packet);
58057429Smarkm		buffer_append(&outgoing_packet, buffer_ptr(&compression_buffer),
58192555Sdes		    buffer_len(&compression_buffer));
58257429Smarkm	}
58357429Smarkm	/* Compute packet length without padding (add checksum, remove padding). */
58457429Smarkm	len = buffer_len(&outgoing_packet) + 4 - 8;
58557429Smarkm
58660573Skris	/* Insert padding. Initialized to zero in packet_start1() */
58757429Smarkm	padding = 8 - len % 8;
58892555Sdes	if (!send_context.plaintext) {
58957429Smarkm		cp = buffer_ptr(&outgoing_packet);
59057429Smarkm		for (i = 0; i < padding; i++) {
59157429Smarkm			if (i % 4 == 0)
592137015Sdes				rnd = arc4random();
593137015Sdes			cp[7 - i] = rnd & 0xff;
594137015Sdes			rnd >>= 8;
59557429Smarkm		}
59657429Smarkm	}
59757429Smarkm	buffer_consume(&outgoing_packet, 8 - padding);
59857429Smarkm
59957429Smarkm	/* Add check bytes. */
60092555Sdes	checksum = ssh_crc32(buffer_ptr(&outgoing_packet),
60165668Skris	    buffer_len(&outgoing_packet));
602162852Sdes	put_u32(buf, checksum);
60357429Smarkm	buffer_append(&outgoing_packet, buf, 4);
60457429Smarkm
60557429Smarkm#ifdef PACKET_DEBUG
60657429Smarkm	fprintf(stderr, "packet_send plain: ");
60757429Smarkm	buffer_dump(&outgoing_packet);
60857429Smarkm#endif
60957429Smarkm
61057429Smarkm	/* Append to output. */
611162852Sdes	put_u32(buf, len);
61257429Smarkm	buffer_append(&output, buf, 4);
61392555Sdes	cp = buffer_append_space(&output, buffer_len(&outgoing_packet));
61492555Sdes	cipher_crypt(&send_context, cp, buffer_ptr(&outgoing_packet),
61592555Sdes	    buffer_len(&outgoing_packet));
61657429Smarkm
61757429Smarkm#ifdef PACKET_DEBUG
61857429Smarkm	fprintf(stderr, "encrypted: ");
61957429Smarkm	buffer_dump(&output);
62057429Smarkm#endif
621181111Sdes	p_send.packets++;
622181111Sdes	p_send.bytes += len + buffer_len(&outgoing_packet);
62357429Smarkm	buffer_clear(&outgoing_packet);
62457429Smarkm
62557429Smarkm	/*
626157016Sdes	 * Note that the packet is now only buffered in output.  It won't be
62757429Smarkm	 * actually sent until packet_write_wait or packet_write_poll is
62857429Smarkm	 * called.
62957429Smarkm	 */
63057429Smarkm}
63157429Smarkm
63298675Sdesvoid
63376259Sgreenset_newkeys(int mode)
63476259Sgreen{
63576259Sgreen	Enc *enc;
63676259Sgreen	Mac *mac;
63776259Sgreen	Comp *comp;
63876259Sgreen	CipherContext *cc;
639124208Sdes	u_int64_t *max_blocks;
640137015Sdes	int crypt_type;
64176259Sgreen
642113908Sdes	debug2("set_newkeys: mode %d", mode);
64376259Sgreen
64492555Sdes	if (mode == MODE_OUT) {
64592555Sdes		cc = &send_context;
646137015Sdes		crypt_type = CIPHER_ENCRYPT;
647124208Sdes		p_send.packets = p_send.blocks = 0;
648124208Sdes		max_blocks = &max_blocks_out;
64992555Sdes	} else {
65092555Sdes		cc = &receive_context;
651137015Sdes		crypt_type = CIPHER_DECRYPT;
652124208Sdes		p_read.packets = p_read.blocks = 0;
653124208Sdes		max_blocks = &max_blocks_in;
65492555Sdes	}
65576259Sgreen	if (newkeys[mode] != NULL) {
656113908Sdes		debug("set_newkeys: rekeying");
65792555Sdes		cipher_cleanup(cc);
65876259Sgreen		enc  = &newkeys[mode]->enc;
65976259Sgreen		mac  = &newkeys[mode]->mac;
66076259Sgreen		comp = &newkeys[mode]->comp;
661181111Sdes		mac_clear(mac);
66276259Sgreen		xfree(enc->name);
66376259Sgreen		xfree(enc->iv);
66476259Sgreen		xfree(enc->key);
66576259Sgreen		xfree(mac->name);
66676259Sgreen		xfree(mac->key);
66776259Sgreen		xfree(comp->name);
66876259Sgreen		xfree(newkeys[mode]);
66976259Sgreen	}
67076259Sgreen	newkeys[mode] = kex_get_newkeys(mode);
67176259Sgreen	if (newkeys[mode] == NULL)
67276259Sgreen		fatal("newkeys: no keys for mode %d", mode);
67376259Sgreen	enc  = &newkeys[mode]->enc;
67476259Sgreen	mac  = &newkeys[mode]->mac;
67576259Sgreen	comp = &newkeys[mode]->comp;
676181111Sdes	if (mac_init(mac) == 0)
67776259Sgreen		mac->enabled = 1;
67876259Sgreen	DBG(debug("cipher_init_context: %d", mode));
67992555Sdes	cipher_init(cc, enc->cipher, enc->key, enc->key_len,
680137015Sdes	    enc->iv, enc->block_size, crypt_type);
68198675Sdes	/* Deleting the keys does not gain extra security */
68298675Sdes	/* memset(enc->iv,  0, enc->block_size);
683181111Sdes	   memset(enc->key, 0, enc->key_len);
684181111Sdes	   memset(mac->key, 0, mac->key_len); */
685149749Sdes	if ((comp->type == COMP_ZLIB ||
686149749Sdes	    (comp->type == COMP_DELAYED && after_authentication)) &&
687149749Sdes	    comp->enabled == 0) {
68876259Sgreen		packet_init_compression();
68976259Sgreen		if (mode == MODE_OUT)
69076259Sgreen			buffer_compress_init_send(6);
69176259Sgreen		else
69276259Sgreen			buffer_compress_init_recv();
69376259Sgreen		comp->enabled = 1;
69476259Sgreen	}
695124208Sdes	/*
696124208Sdes	 * The 2^(blocksize*2) limit is too expensive for 3DES,
697124208Sdes	 * blowfish, etc, so enforce a 1GB limit for small blocksizes.
698124208Sdes	 */
699124208Sdes	if (enc->block_size >= 16)
700124208Sdes		*max_blocks = (u_int64_t)1 << (enc->block_size*2);
701124208Sdes	else
702124208Sdes		*max_blocks = ((u_int64_t)1 << 30) / enc->block_size;
703124208Sdes	if (rekey_limit)
704124208Sdes		*max_blocks = MIN(*max_blocks, rekey_limit / enc->block_size);
70576259Sgreen}
70676259Sgreen
70757429Smarkm/*
708149749Sdes * Delayed compression for SSH2 is enabled after authentication:
709162852Sdes * This happens on the server side after a SSH2_MSG_USERAUTH_SUCCESS is sent,
710149749Sdes * and on the client side after a SSH2_MSG_USERAUTH_SUCCESS is received.
711149749Sdes */
712149749Sdesstatic void
713149749Sdespacket_enable_delayed_compress(void)
714149749Sdes{
715149749Sdes	Comp *comp = NULL;
716149749Sdes	int mode;
717149749Sdes
718149749Sdes	/*
719149749Sdes	 * Remember that we are past the authentication step, so rekeying
720149749Sdes	 * with COMP_DELAYED will turn on compression immediately.
721149749Sdes	 */
722149749Sdes	after_authentication = 1;
723149749Sdes	for (mode = 0; mode < MODE_MAX; mode++) {
724162852Sdes		/* protocol error: USERAUTH_SUCCESS received before NEWKEYS */
725162852Sdes		if (newkeys[mode] == NULL)
726162852Sdes			continue;
727149749Sdes		comp = &newkeys[mode]->comp;
728149749Sdes		if (comp && !comp->enabled && comp->type == COMP_DELAYED) {
729149749Sdes			packet_init_compression();
730149749Sdes			if (mode == MODE_OUT)
731149749Sdes				buffer_compress_init_send(6);
732149749Sdes			else
733149749Sdes				buffer_compress_init_recv();
734149749Sdes			comp->enabled = 1;
735149749Sdes		}
736149749Sdes	}
737149749Sdes}
738149749Sdes
739149749Sdes/*
74060573Skris * Finalize packet in SSH2 format (compress, mac, encrypt, enqueue)
74160573Skris */
74292555Sdesstatic void
743124208Sdespacket_send2_wrapped(void)
74460573Skris{
74592555Sdes	u_char type, *cp, *macbuf = NULL;
74692555Sdes	u_char padlen, pad;
74776259Sgreen	u_int packet_length = 0;
74892555Sdes	u_int i, len;
749137015Sdes	u_int32_t rnd = 0;
75060573Skris	Enc *enc   = NULL;
75160573Skris	Mac *mac   = NULL;
75260573Skris	Comp *comp = NULL;
75360573Skris	int block_size;
75460573Skris
75576259Sgreen	if (newkeys[MODE_OUT] != NULL) {
75676259Sgreen		enc  = &newkeys[MODE_OUT]->enc;
75776259Sgreen		mac  = &newkeys[MODE_OUT]->mac;
75876259Sgreen		comp = &newkeys[MODE_OUT]->comp;
75960573Skris	}
76092555Sdes	block_size = enc ? enc->block_size : 8;
76160573Skris
76260573Skris	cp = buffer_ptr(&outgoing_packet);
76392555Sdes	type = cp[5];
76460573Skris
76560573Skris#ifdef PACKET_DEBUG
76660573Skris	fprintf(stderr, "plain:     ");
76760573Skris	buffer_dump(&outgoing_packet);
76860573Skris#endif
76960573Skris
77060573Skris	if (comp && comp->enabled) {
77160573Skris		len = buffer_len(&outgoing_packet);
77260573Skris		/* skip header, compress only payload */
77360573Skris		buffer_consume(&outgoing_packet, 5);
77460573Skris		buffer_clear(&compression_buffer);
77560573Skris		buffer_compress(&outgoing_packet, &compression_buffer);
77660573Skris		buffer_clear(&outgoing_packet);
77760573Skris		buffer_append(&outgoing_packet, "\0\0\0\0\0", 5);
77860573Skris		buffer_append(&outgoing_packet, buffer_ptr(&compression_buffer),
77960573Skris		    buffer_len(&compression_buffer));
78060573Skris		DBG(debug("compression: raw %d compressed %d", len,
78160573Skris		    buffer_len(&outgoing_packet)));
78260573Skris	}
78360573Skris
78460573Skris	/* sizeof (packet_len + pad_len + payload) */
78560573Skris	len = buffer_len(&outgoing_packet);
78660573Skris
78760573Skris	/*
78860573Skris	 * calc size of padding, alloc space, get random data,
78960573Skris	 * minimum padding is 4 bytes
79060573Skris	 */
79160573Skris	padlen = block_size - (len % block_size);
79260573Skris	if (padlen < 4)
79360573Skris		padlen += block_size;
79492555Sdes	if (extra_pad) {
79592555Sdes		/* will wrap if extra_pad+padlen > 255 */
79692555Sdes		extra_pad  = roundup(extra_pad, block_size);
79792555Sdes		pad = extra_pad - ((len + padlen) % extra_pad);
79898675Sdes		debug3("packet_send2: adding %d (len %d padlen %d extra_pad %d)",
79992555Sdes		    pad, len, padlen, extra_pad);
80092555Sdes		padlen += pad;
80192555Sdes		extra_pad = 0;
80292555Sdes	}
80392555Sdes	cp = buffer_append_space(&outgoing_packet, padlen);
80492555Sdes	if (enc && !send_context.plaintext) {
80560573Skris		/* random padding */
80660573Skris		for (i = 0; i < padlen; i++) {
80760573Skris			if (i % 4 == 0)
808137015Sdes				rnd = arc4random();
809137015Sdes			cp[i] = rnd & 0xff;
810137015Sdes			rnd >>= 8;
81160573Skris		}
81260573Skris	} else {
81360573Skris		/* clear padding */
81460573Skris		memset(cp, 0, padlen);
81560573Skris	}
81660573Skris	/* packet_length includes payload, padding and padding length field */
81760573Skris	packet_length = buffer_len(&outgoing_packet) - 4;
81860573Skris	cp = buffer_ptr(&outgoing_packet);
819162852Sdes	put_u32(cp, packet_length);
82092555Sdes	cp[4] = padlen;
82160573Skris	DBG(debug("send: len %d (includes padlen %d)", packet_length+4, padlen));
82260573Skris
82360573Skris	/* compute MAC over seqnr and packet(length fields, payload, padding) */
82460573Skris	if (mac && mac->enabled) {
825124208Sdes		macbuf = mac_compute(mac, p_send.seqnr,
82692555Sdes		    buffer_ptr(&outgoing_packet),
82776259Sgreen		    buffer_len(&outgoing_packet));
828124208Sdes		DBG(debug("done calc MAC out #%d", p_send.seqnr));
82960573Skris	}
83060573Skris	/* encrypt packet and append to output buffer. */
83192555Sdes	cp = buffer_append_space(&output, buffer_len(&outgoing_packet));
83292555Sdes	cipher_crypt(&send_context, cp, buffer_ptr(&outgoing_packet),
83360573Skris	    buffer_len(&outgoing_packet));
83460573Skris	/* append unencrypted MAC */
83560573Skris	if (mac && mac->enabled)
836162852Sdes		buffer_append(&output, macbuf, mac->mac_len);
83760573Skris#ifdef PACKET_DEBUG
83860573Skris	fprintf(stderr, "encrypted: ");
83960573Skris	buffer_dump(&output);
84060573Skris#endif
84160573Skris	/* increment sequence number for outgoing packets */
842124208Sdes	if (++p_send.seqnr == 0)
843124208Sdes		logit("outgoing seqnr wraps around");
844124208Sdes	if (++p_send.packets == 0)
845124208Sdes		if (!(datafellows & SSH_BUG_NOREKEY))
846124208Sdes			fatal("XXX too many packets with same key");
847124208Sdes	p_send.blocks += (packet_length + 4) / block_size;
848181111Sdes	p_send.bytes += packet_length + 4;
84960573Skris	buffer_clear(&outgoing_packet);
85060573Skris
85176259Sgreen	if (type == SSH2_MSG_NEWKEYS)
85276259Sgreen		set_newkeys(MODE_OUT);
853149749Sdes	else if (type == SSH2_MSG_USERAUTH_SUCCESS && server_side)
854149749Sdes		packet_enable_delayed_compress();
85560573Skris}
85660573Skris
857124208Sdesstatic void
858124208Sdespacket_send2(void)
859124208Sdes{
860124208Sdes	static int rekeying = 0;
861124208Sdes	struct packet *p;
862124208Sdes	u_char type, *cp;
863124208Sdes
864124208Sdes	cp = buffer_ptr(&outgoing_packet);
865124208Sdes	type = cp[5];
866124208Sdes
867124208Sdes	/* during rekeying we can only send key exchange messages */
868124208Sdes	if (rekeying) {
869124208Sdes		if (!((type >= SSH2_MSG_TRANSPORT_MIN) &&
870124208Sdes		    (type <= SSH2_MSG_TRANSPORT_MAX))) {
871124208Sdes			debug("enqueue packet: %u", type);
872124208Sdes			p = xmalloc(sizeof(*p));
873124208Sdes			p->type = type;
874124208Sdes			memcpy(&p->payload, &outgoing_packet, sizeof(Buffer));
875124208Sdes			buffer_init(&outgoing_packet);
876124208Sdes			TAILQ_INSERT_TAIL(&outgoing, p, next);
877124208Sdes			return;
878124208Sdes		}
879124208Sdes	}
880124208Sdes
881124208Sdes	/* rekeying starts with sending KEXINIT */
882124208Sdes	if (type == SSH2_MSG_KEXINIT)
883124208Sdes		rekeying = 1;
884124208Sdes
885124208Sdes	packet_send2_wrapped();
886124208Sdes
887124208Sdes	/* after a NEWKEYS message we can send the complete queue */
888124208Sdes	if (type == SSH2_MSG_NEWKEYS) {
889124208Sdes		rekeying = 0;
890124208Sdes		while ((p = TAILQ_FIRST(&outgoing))) {
891124208Sdes			type = p->type;
892124208Sdes			debug("dequeue packet: %u", type);
893124208Sdes			buffer_free(&outgoing_packet);
894124208Sdes			memcpy(&outgoing_packet, &p->payload,
895124208Sdes			    sizeof(Buffer));
896124208Sdes			TAILQ_REMOVE(&outgoing, p, next);
897124208Sdes			xfree(p);
898124208Sdes			packet_send2_wrapped();
899124208Sdes		}
900124208Sdes	}
901124208Sdes}
902124208Sdes
90360573Skrisvoid
90492555Sdespacket_send(void)
90560573Skris{
90692555Sdes	if (compat20)
90760573Skris		packet_send2();
90860573Skris	else
90960573Skris		packet_send1();
91060573Skris	DBG(debug("packet_send done"));
91160573Skris}
91260573Skris
91360573Skris/*
91457429Smarkm * Waits until a packet has been received, and returns its type.  Note that
91557429Smarkm * no other data is processed until this returns, so this function should not
91657429Smarkm * be used during the interactive session.
91757429Smarkm */
91857429Smarkm
91957429Smarkmint
92092555Sdespacket_read_seqnr(u_int32_t *seqnr_p)
92157429Smarkm{
922181111Sdes	int type, len, ret, ms_remain;
92376259Sgreen	fd_set *setp;
92457429Smarkm	char buf[8192];
925181111Sdes	struct timeval timeout, start, *timeoutp = NULL;
926181111Sdes
92760573Skris	DBG(debug("packet_read()"));
92857429Smarkm
929162852Sdes	setp = (fd_set *)xcalloc(howmany(connection_in+1, NFDBITS),
93076259Sgreen	    sizeof(fd_mask));
93176259Sgreen
93257429Smarkm	/* Since we are blocking, ensure that all written packets have been sent. */
93357429Smarkm	packet_write_wait();
93457429Smarkm
93557429Smarkm	/* Stay in the loop until we have received a complete packet. */
93657429Smarkm	for (;;) {
93757429Smarkm		/* Try to read a packet from the buffer. */
93892555Sdes		type = packet_read_poll_seqnr(seqnr_p);
93992555Sdes		if (!compat20 && (
94060573Skris		    type == SSH_SMSG_SUCCESS
94157429Smarkm		    || type == SSH_SMSG_FAILURE
94257429Smarkm		    || type == SSH_CMSG_EOF
94360573Skris		    || type == SSH_CMSG_EXIT_CONFIRMATION))
94492555Sdes			packet_check_eom();
94557429Smarkm		/* If we got a packet, return it. */
94676259Sgreen		if (type != SSH_MSG_NONE) {
94776259Sgreen			xfree(setp);
94857429Smarkm			return type;
94976259Sgreen		}
95057429Smarkm		/*
95157429Smarkm		 * Otherwise, wait for some data to arrive, add it to the
95257429Smarkm		 * buffer, and try again.
95357429Smarkm		 */
95476259Sgreen		memset(setp, 0, howmany(connection_in + 1, NFDBITS) *
95576259Sgreen		    sizeof(fd_mask));
95676259Sgreen		FD_SET(connection_in, setp);
95757429Smarkm
958181111Sdes		if (packet_timeout_ms > 0) {
959181111Sdes			ms_remain = packet_timeout_ms;
960181111Sdes			timeoutp = &timeout;
961181111Sdes		}
96257429Smarkm		/* Wait for some data to arrive. */
963181111Sdes		for (;;) {
964181111Sdes			if (packet_timeout_ms != -1) {
965181111Sdes				ms_to_timeval(&timeout, ms_remain);
966181111Sdes				gettimeofday(&start, NULL);
967181111Sdes			}
968181111Sdes			if ((ret = select(connection_in + 1, setp, NULL,
969181111Sdes			    NULL, timeoutp)) >= 0)
970181111Sdes				break;
971181111Sdes		   	if (errno != EAGAIN && errno != EINTR &&
972181111Sdes			    errno != EWOULDBLOCK)
973181111Sdes				break;
974181111Sdes			if (packet_timeout_ms == -1)
975181111Sdes				continue;
976181111Sdes			ms_subtract_diff(&start, &ms_remain);
977181111Sdes			if (ms_remain <= 0) {
978181111Sdes				ret = 0;
979181111Sdes				break;
980181111Sdes			}
981181111Sdes		}
982181111Sdes		if (ret == 0) {
983181111Sdes			logit("Connection to %.200s timed out while "
984181111Sdes			    "waiting to read", get_remote_ipaddr());
985181111Sdes			cleanup_exit(255);
986181111Sdes		}
98757429Smarkm		/* Read data from the socket. */
98857429Smarkm		len = read(connection_in, buf, sizeof(buf));
98957429Smarkm		if (len == 0) {
990124208Sdes			logit("Connection closed by %.200s", get_remote_ipaddr());
991126274Sdes			cleanup_exit(255);
99257429Smarkm		}
99357429Smarkm		if (len < 0)
99457429Smarkm			fatal("Read from socket failed: %.100s", strerror(errno));
99557429Smarkm		/* Append it to the buffer. */
99657429Smarkm		packet_process_incoming(buf, len);
99757429Smarkm	}
99857429Smarkm	/* NOTREACHED */
99957429Smarkm}
100057429Smarkm
100192555Sdesint
100292555Sdespacket_read(void)
100392555Sdes{
100492555Sdes	return packet_read_seqnr(NULL);
100592555Sdes}
100692555Sdes
100757429Smarkm/*
100857429Smarkm * Waits until a packet has been received, verifies that its type matches
100957429Smarkm * that given, and gives a fatal error and exits if there is a mismatch.
101057429Smarkm */
101157429Smarkm
101257429Smarkmvoid
101392555Sdespacket_read_expect(int expected_type)
101457429Smarkm{
101557429Smarkm	int type;
101657429Smarkm
101792555Sdes	type = packet_read();
101857429Smarkm	if (type != expected_type)
101957429Smarkm		packet_disconnect("Protocol error: expected packet type %d, got %d",
102060573Skris		    expected_type, type);
102157429Smarkm}
102257429Smarkm
102357429Smarkm/* Checks if a full packet is available in the data received so far via
102457429Smarkm * packet_process_incoming.  If so, reads the packet; otherwise returns
102557429Smarkm * SSH_MSG_NONE.  This does not wait for data from the connection.
102657429Smarkm *
102757429Smarkm * SSH_MSG_DISCONNECT is handled specially here.  Also,
102857429Smarkm * SSH_MSG_IGNORE messages are skipped by this function and are never returned
102957429Smarkm * to higher levels.
103057429Smarkm */
103157429Smarkm
103292555Sdesstatic int
103392555Sdespacket_read_poll1(void)
103457429Smarkm{
103576259Sgreen	u_int len, padded_len;
103692555Sdes	u_char *cp, type;
103776259Sgreen	u_int checksum, stored_checksum;
103857429Smarkm
103957429Smarkm	/* Check if input size is less than minimum packet size. */
104057429Smarkm	if (buffer_len(&input) < 4 + 8)
104157429Smarkm		return SSH_MSG_NONE;
104257429Smarkm	/* Get length of incoming packet. */
104392555Sdes	cp = buffer_ptr(&input);
1044162852Sdes	len = get_u32(cp);
104557429Smarkm	if (len < 1 + 2 + 2 || len > 256 * 1024)
1046113908Sdes		packet_disconnect("Bad packet length %u.", len);
104757429Smarkm	padded_len = (len + 8) & ~7;
104857429Smarkm
104957429Smarkm	/* Check if the packet has been entirely received. */
105057429Smarkm	if (buffer_len(&input) < 4 + padded_len)
105157429Smarkm		return SSH_MSG_NONE;
105257429Smarkm
105357429Smarkm	/* The entire packet is in buffer. */
105457429Smarkm
105557429Smarkm	/* Consume packet length. */
105657429Smarkm	buffer_consume(&input, 4);
105757429Smarkm
105892555Sdes	/*
105992555Sdes	 * Cryptographic attack detector for ssh
106092555Sdes	 * (C)1998 CORE-SDI, Buenos Aires Argentina
106192555Sdes	 * Ariel Futoransky(futo@core-sdi.com)
106292555Sdes	 */
1063162852Sdes	if (!receive_context.plaintext) {
1064162852Sdes		switch (detect_attack(buffer_ptr(&input), padded_len)) {
1065162852Sdes		case DEATTACK_DETECTED:
1066162852Sdes			packet_disconnect("crc32 compensation attack: "
1067162852Sdes			    "network attack detected");
1068162852Sdes		case DEATTACK_DOS_DETECTED:
1069162852Sdes			packet_disconnect("deattack denial of "
1070162852Sdes			    "service detected");
1071162852Sdes		}
1072162852Sdes	}
107392555Sdes
107492555Sdes	/* Decrypt data to incoming_packet. */
107557429Smarkm	buffer_clear(&incoming_packet);
107692555Sdes	cp = buffer_append_space(&incoming_packet, padded_len);
107792555Sdes	cipher_crypt(&receive_context, cp, buffer_ptr(&input), padded_len);
107892555Sdes
107957429Smarkm	buffer_consume(&input, padded_len);
108057429Smarkm
108157429Smarkm#ifdef PACKET_DEBUG
108257429Smarkm	fprintf(stderr, "read_poll plain: ");
108357429Smarkm	buffer_dump(&incoming_packet);
108457429Smarkm#endif
108557429Smarkm
108657429Smarkm	/* Compute packet checksum. */
108792555Sdes	checksum = ssh_crc32(buffer_ptr(&incoming_packet),
108860573Skris	    buffer_len(&incoming_packet) - 4);
108957429Smarkm
109057429Smarkm	/* Skip padding. */
109157429Smarkm	buffer_consume(&incoming_packet, 8 - len % 8);
109257429Smarkm
109357429Smarkm	/* Test check bytes. */
109457429Smarkm	if (len != buffer_len(&incoming_packet))
109592555Sdes		packet_disconnect("packet_read_poll1: len %d != buffer_len %d.",
109660573Skris		    len, buffer_len(&incoming_packet));
109757429Smarkm
109892555Sdes	cp = (u_char *)buffer_ptr(&incoming_packet) + len - 4;
1099162852Sdes	stored_checksum = get_u32(cp);
110057429Smarkm	if (checksum != stored_checksum)
110157429Smarkm		packet_disconnect("Corrupted check bytes on input.");
110257429Smarkm	buffer_consume_end(&incoming_packet, 4);
110357429Smarkm
110457429Smarkm	if (packet_compression) {
110557429Smarkm		buffer_clear(&compression_buffer);
110657429Smarkm		buffer_uncompress(&incoming_packet, &compression_buffer);
110757429Smarkm		buffer_clear(&incoming_packet);
110857429Smarkm		buffer_append(&incoming_packet, buffer_ptr(&compression_buffer),
110960573Skris		    buffer_len(&compression_buffer));
111057429Smarkm	}
1111181111Sdes	p_read.packets++;
1112181111Sdes	p_read.bytes += padded_len + 4;
111392555Sdes	type = buffer_get_char(&incoming_packet);
1114146998Sdes	if (type < SSH_MSG_MIN || type > SSH_MSG_MAX)
1115146998Sdes		packet_disconnect("Invalid ssh1 packet type: %d", type);
111692555Sdes	return type;
111760573Skris}
111857429Smarkm
111992555Sdesstatic int
112092555Sdespacket_read_poll2(u_int32_t *seqnr_p)
112160573Skris{
112276259Sgreen	static u_int packet_length = 0;
112376259Sgreen	u_int padlen, need;
112492555Sdes	u_char *macbuf, *cp, type;
1125149749Sdes	u_int maclen, block_size;
112660573Skris	Enc *enc   = NULL;
112760573Skris	Mac *mac   = NULL;
112860573Skris	Comp *comp = NULL;
112957429Smarkm
113076259Sgreen	if (newkeys[MODE_IN] != NULL) {
113176259Sgreen		enc  = &newkeys[MODE_IN]->enc;
113276259Sgreen		mac  = &newkeys[MODE_IN]->mac;
113376259Sgreen		comp = &newkeys[MODE_IN]->comp;
113457429Smarkm	}
113560573Skris	maclen = mac && mac->enabled ? mac->mac_len : 0;
113692555Sdes	block_size = enc ? enc->block_size : 8;
113760573Skris
113860573Skris	if (packet_length == 0) {
113960573Skris		/*
114060573Skris		 * check if input size is less than the cipher block size,
114160573Skris		 * decrypt first block and extract length of incoming packet
114260573Skris		 */
114360573Skris		if (buffer_len(&input) < block_size)
114460573Skris			return SSH_MSG_NONE;
114560573Skris		buffer_clear(&incoming_packet);
114692555Sdes		cp = buffer_append_space(&incoming_packet, block_size);
114792555Sdes		cipher_crypt(&receive_context, cp, buffer_ptr(&input),
114860573Skris		    block_size);
114992555Sdes		cp = buffer_ptr(&incoming_packet);
1150162852Sdes		packet_length = get_u32(cp);
115160573Skris		if (packet_length < 1 + 4 || packet_length > 256 * 1024) {
1152124208Sdes#ifdef PACKET_DEBUG
115360573Skris			buffer_dump(&incoming_packet);
1154124208Sdes#endif
1155113908Sdes			packet_disconnect("Bad packet length %u.", packet_length);
115660573Skris		}
1157113908Sdes		DBG(debug("input: packet len %u", packet_length+4));
115860573Skris		buffer_consume(&input, block_size);
115960573Skris	}
116060573Skris	/* we have a partial packet of block_size bytes */
116160573Skris	need = 4 + packet_length - block_size;
116260573Skris	DBG(debug("partial packet %d, need %d, maclen %d", block_size,
116360573Skris	    need, maclen));
116460573Skris	if (need % block_size != 0)
116560573Skris		fatal("padding error: need %d block %d mod %d",
116660573Skris		    need, block_size, need % block_size);
116760573Skris	/*
116860573Skris	 * check if the entire packet has been received and
116960573Skris	 * decrypt into incoming_packet
117060573Skris	 */
117160573Skris	if (buffer_len(&input) < need + maclen)
117260573Skris		return SSH_MSG_NONE;
117360573Skris#ifdef PACKET_DEBUG
117460573Skris	fprintf(stderr, "read_poll enc/full: ");
117560573Skris	buffer_dump(&input);
117660573Skris#endif
117792555Sdes	cp = buffer_append_space(&incoming_packet, need);
117892555Sdes	cipher_crypt(&receive_context, cp, buffer_ptr(&input), need);
117960573Skris	buffer_consume(&input, need);
118060573Skris	/*
118160573Skris	 * compute MAC over seqnr and packet,
118260573Skris	 * increment sequence number for incoming packet
118360573Skris	 */
118460573Skris	if (mac && mac->enabled) {
1185124208Sdes		macbuf = mac_compute(mac, p_read.seqnr,
118692555Sdes		    buffer_ptr(&incoming_packet),
118776259Sgreen		    buffer_len(&incoming_packet));
118860573Skris		if (memcmp(macbuf, buffer_ptr(&input), mac->mac_len) != 0)
118969587Sgreen			packet_disconnect("Corrupted MAC on input.");
1190124208Sdes		DBG(debug("MAC #%d ok", p_read.seqnr));
119160573Skris		buffer_consume(&input, mac->mac_len);
119260573Skris	}
119392555Sdes	if (seqnr_p != NULL)
1194124208Sdes		*seqnr_p = p_read.seqnr;
1195124208Sdes	if (++p_read.seqnr == 0)
1196124208Sdes		logit("incoming seqnr wraps around");
1197124208Sdes	if (++p_read.packets == 0)
1198124208Sdes		if (!(datafellows & SSH_BUG_NOREKEY))
1199124208Sdes			fatal("XXX too many packets with same key");
1200124208Sdes	p_read.blocks += (packet_length + 4) / block_size;
1201181111Sdes	p_read.bytes += packet_length + 4;
120260573Skris
120360573Skris	/* get padlen */
120492555Sdes	cp = buffer_ptr(&incoming_packet);
120592555Sdes	padlen = cp[4];
120660573Skris	DBG(debug("input: padlen %d", padlen));
120760573Skris	if (padlen < 4)
120860573Skris		packet_disconnect("Corrupted padlen %d on input.", padlen);
120960573Skris
121060573Skris	/* skip packet size + padlen, discard padding */
121160573Skris	buffer_consume(&incoming_packet, 4 + 1);
121260573Skris	buffer_consume_end(&incoming_packet, padlen);
121360573Skris
121460573Skris	DBG(debug("input: len before de-compress %d", buffer_len(&incoming_packet)));
121560573Skris	if (comp && comp->enabled) {
121660573Skris		buffer_clear(&compression_buffer);
121760573Skris		buffer_uncompress(&incoming_packet, &compression_buffer);
121860573Skris		buffer_clear(&incoming_packet);
121960573Skris		buffer_append(&incoming_packet, buffer_ptr(&compression_buffer),
122060573Skris		    buffer_len(&compression_buffer));
1221106121Sdes		DBG(debug("input: len after de-compress %d",
1222106121Sdes		    buffer_len(&incoming_packet)));
122360573Skris	}
122460573Skris	/*
122560573Skris	 * get packet type, implies consume.
122660573Skris	 * return length of payload (without type field)
122760573Skris	 */
122892555Sdes	type = buffer_get_char(&incoming_packet);
1229146998Sdes	if (type < SSH2_MSG_MIN || type >= SSH2_MSG_LOCAL_MIN)
1230146998Sdes		packet_disconnect("Invalid ssh2 packet type: %d", type);
123176259Sgreen	if (type == SSH2_MSG_NEWKEYS)
123276259Sgreen		set_newkeys(MODE_IN);
1233149749Sdes	else if (type == SSH2_MSG_USERAUTH_SUCCESS && !server_side)
1234149749Sdes		packet_enable_delayed_compress();
123560573Skris#ifdef PACKET_DEBUG
123676259Sgreen	fprintf(stderr, "read/plain[%d]:\r\n", type);
123760573Skris	buffer_dump(&incoming_packet);
123860573Skris#endif
123992555Sdes	/* reset for next packet */
124092555Sdes	packet_length = 0;
124192555Sdes	return type;
124257429Smarkm}
124357429Smarkm
124460573Skrisint
124592555Sdespacket_read_poll_seqnr(u_int32_t *seqnr_p)
124660573Skris{
124799060Sdes	u_int reason, seqnr;
124892555Sdes	u_char type;
124960573Skris	char *msg;
125092555Sdes
125160573Skris	for (;;) {
125292555Sdes		if (compat20) {
125392555Sdes			type = packet_read_poll2(seqnr_p);
1254181111Sdes			if (type) {
1255181111Sdes				keep_alive_timeouts = 0;
125660573Skris				DBG(debug("received packet type %d", type));
1257181111Sdes			}
125892555Sdes			switch (type) {
125960573Skris			case SSH2_MSG_IGNORE:
1260181111Sdes				debug3("Received SSH2_MSG_IGNORE");
126160573Skris				break;
126260573Skris			case SSH2_MSG_DEBUG:
126360573Skris				packet_get_char();
126460573Skris				msg = packet_get_string(NULL);
126560573Skris				debug("Remote: %.900s", msg);
126660573Skris				xfree(msg);
126760573Skris				msg = packet_get_string(NULL);
126860573Skris				xfree(msg);
126960573Skris				break;
127060573Skris			case SSH2_MSG_DISCONNECT:
127160573Skris				reason = packet_get_int();
127260573Skris				msg = packet_get_string(NULL);
1273124208Sdes				logit("Received disconnect from %s: %u: %.400s",
127499060Sdes				    get_remote_ipaddr(), reason, msg);
127560573Skris				xfree(msg);
1276126274Sdes				cleanup_exit(255);
127760573Skris				break;
127892555Sdes			case SSH2_MSG_UNIMPLEMENTED:
127992555Sdes				seqnr = packet_get_int();
128099060Sdes				debug("Received SSH2_MSG_UNIMPLEMENTED for %u",
128199060Sdes				    seqnr);
128292555Sdes				break;
128360573Skris			default:
128460573Skris				return type;
128576259Sgreen			}
128660573Skris		} else {
128792555Sdes			type = packet_read_poll1();
128892555Sdes			switch (type) {
128960573Skris			case SSH_MSG_IGNORE:
129060573Skris				break;
129160573Skris			case SSH_MSG_DEBUG:
129260573Skris				msg = packet_get_string(NULL);
129360573Skris				debug("Remote: %.900s", msg);
129460573Skris				xfree(msg);
129560573Skris				break;
129660573Skris			case SSH_MSG_DISCONNECT:
129760573Skris				msg = packet_get_string(NULL);
1298124208Sdes				logit("Received disconnect from %s: %.400s",
129999060Sdes				    get_remote_ipaddr(), msg);
1300126274Sdes				cleanup_exit(255);
130160573Skris				break;
130260573Skris			default:
130392555Sdes				if (type)
130460573Skris					DBG(debug("received packet type %d", type));
130560573Skris				return type;
130676259Sgreen			}
130760573Skris		}
130860573Skris	}
130960573Skris}
131060573Skris
131192555Sdesint
131292555Sdespacket_read_poll(void)
131392555Sdes{
131492555Sdes	return packet_read_poll_seqnr(NULL);
131592555Sdes}
131692555Sdes
131757429Smarkm/*
131857429Smarkm * Buffers the given amount of input characters.  This is intended to be used
131957429Smarkm * together with packet_read_poll.
132057429Smarkm */
132157429Smarkm
132257429Smarkmvoid
132376259Sgreenpacket_process_incoming(const char *buf, u_int len)
132457429Smarkm{
132557429Smarkm	buffer_append(&input, buf, len);
132657429Smarkm}
132757429Smarkm
132857429Smarkm/* Returns a character from the packet. */
132957429Smarkm
133076259Sgreenu_int
133192555Sdespacket_get_char(void)
133257429Smarkm{
133357429Smarkm	char ch;
1334106121Sdes
133557429Smarkm	buffer_get(&incoming_packet, &ch, 1);
133676259Sgreen	return (u_char) ch;
133757429Smarkm}
133857429Smarkm
133957429Smarkm/* Returns an integer from the packet data. */
134057429Smarkm
134176259Sgreenu_int
134292555Sdespacket_get_int(void)
134357429Smarkm{
134457429Smarkm	return buffer_get_int(&incoming_packet);
134557429Smarkm}
134657429Smarkm
134757429Smarkm/*
134857429Smarkm * Returns an arbitrary precision integer from the packet data.  The integer
134957429Smarkm * must have been initialized before this call.
135057429Smarkm */
135157429Smarkm
135257429Smarkmvoid
135392555Sdespacket_get_bignum(BIGNUM * value)
135457429Smarkm{
135592555Sdes	buffer_get_bignum(&incoming_packet, value);
135657429Smarkm}
135757429Smarkm
135860573Skrisvoid
135992555Sdespacket_get_bignum2(BIGNUM * value)
136060573Skris{
136192555Sdes	buffer_get_bignum2(&incoming_packet, value);
136260573Skris}
136360573Skris
136492555Sdesvoid *
1365149749Sdespacket_get_raw(u_int *length_ptr)
136660573Skris{
1367149749Sdes	u_int bytes = buffer_len(&incoming_packet);
1368106121Sdes
136960573Skris	if (length_ptr != NULL)
137060573Skris		*length_ptr = bytes;
137160573Skris	return buffer_ptr(&incoming_packet);
137260573Skris}
137360573Skris
137460573Skrisint
137560573Skrispacket_remaining(void)
137660573Skris{
137760573Skris	return buffer_len(&incoming_packet);
137860573Skris}
137960573Skris
138057429Smarkm/*
138157429Smarkm * Returns a string from the packet data.  The string is allocated using
138257429Smarkm * xmalloc; it is the responsibility of the calling program to free it when
138357429Smarkm * no longer needed.  The length_ptr argument may be NULL, or point to an
138457429Smarkm * integer into which the length of the string is stored.
138557429Smarkm */
138657429Smarkm
138792555Sdesvoid *
138876259Sgreenpacket_get_string(u_int *length_ptr)
138957429Smarkm{
139057429Smarkm	return buffer_get_string(&incoming_packet, length_ptr);
139157429Smarkm}
139257429Smarkm
1393181111Sdesvoid *
1394181111Sdespacket_get_string_ptr(u_int *length_ptr)
1395181111Sdes{
1396181111Sdes	return buffer_get_string_ptr(&incoming_packet, length_ptr);
1397181111Sdes}
1398181111Sdes
139957429Smarkm/*
140057429Smarkm * Sends a diagnostic message from the server to the client.  This message
140157429Smarkm * can be sent at any time (but not while constructing another message). The
140257429Smarkm * message is printed immediately, but only if the client is being executed
140357429Smarkm * in verbose mode.  These messages are primarily intended to ease debugging
140457429Smarkm * authentication problems.   The length of the formatted message must not
140557429Smarkm * exceed 1024 bytes.  This will automatically call packet_write_wait.
140657429Smarkm */
140757429Smarkm
140857429Smarkmvoid
140957429Smarkmpacket_send_debug(const char *fmt,...)
141057429Smarkm{
141157429Smarkm	char buf[1024];
141257429Smarkm	va_list args;
141357429Smarkm
141476259Sgreen	if (compat20 && (datafellows & SSH_BUG_DEBUG))
141576259Sgreen		return;
141676259Sgreen
141757429Smarkm	va_start(args, fmt);
141857429Smarkm	vsnprintf(buf, sizeof(buf), fmt, args);
141957429Smarkm	va_end(args);
142057429Smarkm
142160573Skris	if (compat20) {
142260573Skris		packet_start(SSH2_MSG_DEBUG);
142360573Skris		packet_put_char(0);	/* bool: always display */
142460573Skris		packet_put_cstring(buf);
142560573Skris		packet_put_cstring("");
142660573Skris	} else {
142760573Skris		packet_start(SSH_MSG_DEBUG);
142860573Skris		packet_put_cstring(buf);
142960573Skris	}
143057429Smarkm	packet_send();
143157429Smarkm	packet_write_wait();
143257429Smarkm}
143357429Smarkm
143457429Smarkm/*
143557429Smarkm * Logs the error plus constructs and sends a disconnect packet, closes the
143657429Smarkm * connection, and exits.  This function never returns. The error message
143757429Smarkm * should not contain a newline.  The length of the formatted message must
143857429Smarkm * not exceed 1024 bytes.
143957429Smarkm */
144057429Smarkm
144157429Smarkmvoid
144257429Smarkmpacket_disconnect(const char *fmt,...)
144357429Smarkm{
144457429Smarkm	char buf[1024];
144557429Smarkm	va_list args;
144657429Smarkm	static int disconnecting = 0;
1447106121Sdes
144857429Smarkm	if (disconnecting)	/* Guard against recursive invocations. */
144957429Smarkm		fatal("packet_disconnect called recursively.");
145057429Smarkm	disconnecting = 1;
145157429Smarkm
145257429Smarkm	/*
145357429Smarkm	 * Format the message.  Note that the caller must make sure the
145457429Smarkm	 * message is of limited size.
145557429Smarkm	 */
145657429Smarkm	va_start(args, fmt);
145757429Smarkm	vsnprintf(buf, sizeof(buf), fmt, args);
145857429Smarkm	va_end(args);
145957429Smarkm
1460113908Sdes	/* Display the error locally */
1461124208Sdes	logit("Disconnecting: %.100s", buf);
1462113908Sdes
146357429Smarkm	/* Send the disconnect message to the other side, and wait for it to get sent. */
146460573Skris	if (compat20) {
146560573Skris		packet_start(SSH2_MSG_DISCONNECT);
146660573Skris		packet_put_int(SSH2_DISCONNECT_PROTOCOL_ERROR);
146760573Skris		packet_put_cstring(buf);
146860573Skris		packet_put_cstring("");
146960573Skris	} else {
147060573Skris		packet_start(SSH_MSG_DISCONNECT);
147192555Sdes		packet_put_cstring(buf);
147260573Skris	}
147357429Smarkm	packet_send();
147457429Smarkm	packet_write_wait();
147557429Smarkm
147657429Smarkm	/* Stop listening for connections. */
147792555Sdes	channel_close_all();
147857429Smarkm
147957429Smarkm	/* Close the connection. */
148057429Smarkm	packet_close();
1481126274Sdes	cleanup_exit(255);
148257429Smarkm}
148357429Smarkm
148457429Smarkm/* Checks if there is any buffered output, and tries to write some of the output. */
148557429Smarkm
148657429Smarkmvoid
148792555Sdespacket_write_poll(void)
148857429Smarkm{
148957429Smarkm	int len = buffer_len(&output);
1490106121Sdes
149157429Smarkm	if (len > 0) {
149257429Smarkm		len = write(connection_out, buffer_ptr(&output), len);
1493181111Sdes		if (len == -1) {
1494181111Sdes			if (errno == EINTR || errno == EAGAIN ||
1495181111Sdes			    errno == EWOULDBLOCK)
149657429Smarkm				return;
1497181111Sdes			fatal("Write failed: %.100s", strerror(errno));
149857429Smarkm		}
1499181111Sdes		if (len == 0)
1500181111Sdes			fatal("Write connection closed");
150157429Smarkm		buffer_consume(&output, len);
150257429Smarkm	}
150357429Smarkm}
150457429Smarkm
1505181111Sdes
150657429Smarkm/*
150757429Smarkm * Calls packet_write_poll repeatedly until all pending output data has been
150857429Smarkm * written.
150957429Smarkm */
151057429Smarkm
151157429Smarkmvoid
151292555Sdespacket_write_wait(void)
151357429Smarkm{
151476259Sgreen	fd_set *setp;
1515181111Sdes	int ret, ms_remain;
1516181111Sdes	struct timeval start, timeout, *timeoutp = NULL;
151776259Sgreen
1518162852Sdes	setp = (fd_set *)xcalloc(howmany(connection_out + 1, NFDBITS),
151976259Sgreen	    sizeof(fd_mask));
152057429Smarkm	packet_write_poll();
152157429Smarkm	while (packet_have_data_to_write()) {
152276259Sgreen		memset(setp, 0, howmany(connection_out + 1, NFDBITS) *
152376259Sgreen		    sizeof(fd_mask));
152476259Sgreen		FD_SET(connection_out, setp);
1525181111Sdes
1526181111Sdes		if (packet_timeout_ms > 0) {
1527181111Sdes			ms_remain = packet_timeout_ms;
1528181111Sdes			timeoutp = &timeout;
1529181111Sdes		}
1530181111Sdes		for (;;) {
1531181111Sdes			if (packet_timeout_ms != -1) {
1532181111Sdes				ms_to_timeval(&timeout, ms_remain);
1533181111Sdes				gettimeofday(&start, NULL);
1534181111Sdes			}
1535181111Sdes			if ((ret = select(connection_out + 1, NULL, setp,
1536181111Sdes			    NULL, timeoutp)) >= 0)
1537181111Sdes				break;
1538181111Sdes		   	if (errno != EAGAIN && errno != EINTR &&
1539181111Sdes			    errno != EWOULDBLOCK)
1540181111Sdes				break;
1541181111Sdes			if (packet_timeout_ms == -1)
1542181111Sdes				continue;
1543181111Sdes			ms_subtract_diff(&start, &ms_remain);
1544181111Sdes			if (ms_remain <= 0) {
1545181111Sdes				ret = 0;
1546181111Sdes				break;
1547181111Sdes			}
1548181111Sdes		}
1549181111Sdes		if (ret == 0) {
1550181111Sdes			logit("Connection to %.200s timed out while "
1551181111Sdes			    "waiting to write", get_remote_ipaddr());
1552181111Sdes			cleanup_exit(255);
1553181111Sdes		}
155457429Smarkm		packet_write_poll();
155557429Smarkm	}
155676259Sgreen	xfree(setp);
155757429Smarkm}
155857429Smarkm
155957429Smarkm/* Returns true if there is buffered data to write to the connection. */
156057429Smarkm
156157429Smarkmint
156292555Sdespacket_have_data_to_write(void)
156357429Smarkm{
156457429Smarkm	return buffer_len(&output) != 0;
156557429Smarkm}
156657429Smarkm
156757429Smarkm/* Returns true if there is not too much data to write to the connection. */
156857429Smarkm
156957429Smarkmint
157092555Sdespacket_not_very_much_data_to_write(void)
157157429Smarkm{
157257429Smarkm	if (interactive_mode)
157357429Smarkm		return buffer_len(&output) < 16384;
157457429Smarkm	else
157557429Smarkm		return buffer_len(&output) < 128 * 1024;
157657429Smarkm}
157757429Smarkm
1578124208Sdes
1579113908Sdesstatic void
1580113908Sdespacket_set_tos(int interactive)
1581113908Sdes{
1582126274Sdes#if defined(IP_TOS) && !defined(IP_TOS_IS_BROKEN)
1583113908Sdes	int tos = interactive ? IPTOS_LOWDELAY : IPTOS_THROUGHPUT;
1584113908Sdes
1585113908Sdes	if (!packet_connection_is_on_socket() ||
1586113908Sdes	    !packet_connection_is_ipv4())
1587113908Sdes		return;
1588113908Sdes	if (setsockopt(connection_in, IPPROTO_IP, IP_TOS, &tos,
1589113908Sdes	    sizeof(tos)) < 0)
1590113908Sdes		error("setsockopt IP_TOS %d: %.100s:",
1591113908Sdes		    tos, strerror(errno));
1592126274Sdes#endif
1593113908Sdes}
1594113908Sdes
159557429Smarkm/* Informs that the current session is interactive.  Sets IP flags for that. */
159657429Smarkm
159757429Smarkmvoid
159876259Sgreenpacket_set_interactive(int interactive)
159957429Smarkm{
160076259Sgreen	static int called = 0;
160157429Smarkm
160276259Sgreen	if (called)
160376259Sgreen		return;
160476259Sgreen	called = 1;
160576259Sgreen
160657429Smarkm	/* Record that we are in interactive mode. */
160757429Smarkm	interactive_mode = interactive;
160857429Smarkm
160957429Smarkm	/* Only set socket options if using a socket.  */
161057429Smarkm	if (!packet_connection_is_on_socket())
1611116791Sdes		return;
1612162852Sdes	set_nodelay(connection_in);
1613113908Sdes	packet_set_tos(interactive);
161457429Smarkm}
161557429Smarkm
161657429Smarkm/* Returns true if the current connection is interactive. */
161757429Smarkm
161857429Smarkmint
161992555Sdespacket_is_interactive(void)
162057429Smarkm{
162157429Smarkm	return interactive_mode;
162257429Smarkm}
162357429Smarkm
1624137015Sdesint
1625124208Sdespacket_set_maxsize(u_int s)
162657429Smarkm{
162757429Smarkm	static int called = 0;
1628106121Sdes
162957429Smarkm	if (called) {
1630124208Sdes		logit("packet_set_maxsize: called twice: old %d new %d",
163160573Skris		    max_packet_size, s);
163257429Smarkm		return -1;
163357429Smarkm	}
163457429Smarkm	if (s < 4 * 1024 || s > 1024 * 1024) {
1635124208Sdes		logit("packet_set_maxsize: bad size %d", s);
163657429Smarkm		return -1;
163757429Smarkm	}
163892555Sdes	called = 1;
163992555Sdes	debug("packet_set_maxsize: setting to %d", s);
164057429Smarkm	max_packet_size = s;
164157429Smarkm	return s;
164257429Smarkm}
164376259Sgreen
164492555Sdes/* roundup current message to pad bytes */
164592555Sdesvoid
164692555Sdespacket_add_padding(u_char pad)
164792555Sdes{
164892555Sdes	extra_pad = pad;
164992555Sdes}
165092555Sdes
165176259Sgreen/*
165276259Sgreen * 9.2.  Ignored Data Message
165376259Sgreen *
165476259Sgreen *   byte      SSH_MSG_IGNORE
165576259Sgreen *   string    data
165676259Sgreen *
165776259Sgreen * All implementations MUST understand (and ignore) this message at any
165876259Sgreen * time (after receiving the protocol version). No implementation is
165976259Sgreen * required to send them. This message can be used as an additional
166076259Sgreen * protection measure against advanced traffic analysis techniques.
166176259Sgreen */
166276259Sgreenvoid
166376259Sgreenpacket_send_ignore(int nbytes)
166476259Sgreen{
1665137015Sdes	u_int32_t rnd = 0;
166676259Sgreen	int i;
166776259Sgreen
166876259Sgreen	packet_start(compat20 ? SSH2_MSG_IGNORE : SSH_MSG_IGNORE);
166976259Sgreen	packet_put_int(nbytes);
167092555Sdes	for (i = 0; i < nbytes; i++) {
167176259Sgreen		if (i % 4 == 0)
1672137015Sdes			rnd = arc4random();
1673162852Sdes		packet_put_char((u_char)rnd & 0xff);
1674137015Sdes		rnd >>= 8;
167576259Sgreen	}
167676259Sgreen}
1677124208Sdes
1678137015Sdes#define MAX_PACKETS	(1U<<31)
1679124208Sdesint
1680124208Sdespacket_need_rekeying(void)
1681124208Sdes{
1682124208Sdes	if (datafellows & SSH_BUG_NOREKEY)
1683124208Sdes		return 0;
1684124208Sdes	return
1685124208Sdes	    (p_send.packets > MAX_PACKETS) ||
1686124208Sdes	    (p_read.packets > MAX_PACKETS) ||
1687124208Sdes	    (max_blocks_out && (p_send.blocks > max_blocks_out)) ||
1688124208Sdes	    (max_blocks_in  && (p_read.blocks > max_blocks_in));
1689124208Sdes}
1690124208Sdes
1691124208Sdesvoid
1692124208Sdespacket_set_rekey_limit(u_int32_t bytes)
1693124208Sdes{
1694124208Sdes	rekey_limit = bytes;
1695124208Sdes}
1696149749Sdes
1697149749Sdesvoid
1698149749Sdespacket_set_server(void)
1699149749Sdes{
1700149749Sdes	server_side = 1;
1701149749Sdes}
1702149749Sdes
1703149749Sdesvoid
1704149749Sdespacket_set_authenticated(void)
1705149749Sdes{
1706149749Sdes	after_authentication = 1;
1707149749Sdes}
1708