packet.c revision 181111
198937Sdes/* $OpenBSD: packet.c,v 1.157 2008/07/10 18:08:11 markus Exp $ */
298937Sdes/*
398937Sdes * Author: Tatu Ylonen <ylo@cs.hut.fi>
498937Sdes * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
598937Sdes *                    All rights reserved
698937Sdes * This file contains code implementing the packet protocol and communication
798937Sdes * with the other side.  This same code is used both on client and server side.
898937Sdes *
998937Sdes * As far as I am concerned, the code I have written for this software
1098937Sdes * can be used freely for any purpose.  Any derived versions of this
1198937Sdes * software must be clearly marked as such, and if the derived work is
1298937Sdes * incompatible with the protocol description in the RFC file, it must be
1398937Sdes * called by a name other than "ssh" or "Secure Shell".
1498937Sdes *
1598937Sdes *
1698937Sdes * SSH2 packet format added by Markus Friedl.
1798937Sdes * Copyright (c) 2000, 2001 Markus Friedl.  All rights reserved.
1898937Sdes *
1998937Sdes * Redistribution and use in source and binary forms, with or without
2098937Sdes * modification, are permitted provided that the following conditions
2198937Sdes * are met:
2298937Sdes * 1. Redistributions of source code must retain the above copyright
2398937Sdes *    notice, this list of conditions and the following disclaimer.
2498937Sdes * 2. Redistributions in binary form must reproduce the above copyright
2598937Sdes *    notice, this list of conditions and the following disclaimer in the
2698937Sdes *    documentation and/or other materials provided with the distribution.
2798937Sdes *
28147005Sdes * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
29147005Sdes * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
30147005Sdes * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
31147005Sdes * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
32147005Sdes * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
33147005Sdes * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
34147005Sdes * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
35147005Sdes * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
36147005Sdes * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
37147005Sdes * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
38147005Sdes */
39147005Sdes
40147005Sdes#include "includes.h"
41147005Sdes
42147005Sdes#include <sys/types.h>
43147005Sdes#include "openbsd-compat/sys-queue.h"
44147005Sdes#include <sys/param.h>
45147005Sdes#include <sys/socket.h>
46147005Sdes#ifdef HAVE_SYS_TIME_H
47147005Sdes# include <sys/time.h>
48147005Sdes#endif
4998937Sdes
5098937Sdes#include <netinet/in.h>
5198937Sdes#include <netinet/ip.h>
5298937Sdes#include <arpa/inet.h>
5398937Sdes
54147005Sdes#include <errno.h>
55147005Sdes#include <stdarg.h>
56147005Sdes#include <stdio.h>
57147005Sdes#include <stdlib.h>
58147005Sdes#include <string.h>
59147005Sdes#include <unistd.h>
60147005Sdes#include <signal.h>
61147005Sdes
62147005Sdes#include "xmalloc.h"
63147005Sdes#include "buffer.h"
64147005Sdes#include "packet.h"
65147005Sdes#include "crc32.h"
66147005Sdes#include "compress.h"
67147005Sdes#include "deattack.h"
68147005Sdes#include "channels.h"
69147005Sdes#include "compat.h"
70147005Sdes#include "ssh1.h"
71147005Sdes#include "ssh2.h"
72147005Sdes#include "cipher.h"
73147005Sdes#include "key.h"
74147005Sdes#include "kex.h"
75147005Sdes#include "mac.h"
76147005Sdes#include "log.h"
77147005Sdes#include "canohost.h"
78147005Sdes#include "misc.h"
79147005Sdes#include "ssh.h"
80147005Sdes
81147005Sdes#ifdef PACKET_DEBUG
82147005Sdes#define DBG(x) x
83147005Sdes#else
84147005Sdes#define DBG(x)
85147005Sdes#endif
86147005Sdes
87147005Sdes/*
88147005Sdes * This variable contains the file descriptors used for communicating with
89147005Sdes * the other side.  connection_in is used for reading; connection_out for
90147005Sdes * writing.  These can be the same descriptor, in which case it is assumed to
91147005Sdes * be a socket.
92147005Sdes */
93147005Sdesstatic int connection_in = -1;
94147005Sdesstatic int connection_out = -1;
95147005Sdes
96147005Sdes/* Protocol flags for the remote side. */
97147005Sdesstatic u_int remote_protocol_flags = 0;
98147005Sdes
99147005Sdes/* Encryption context for receiving data.  This is only used for decryption. */
100147005Sdesstatic CipherContext receive_context;
101147005Sdes
102147005Sdes/* Encryption context for sending data.  This is only used for encryption. */
103147005Sdesstatic CipherContext send_context;
104147005Sdes
105147005Sdes/* Buffer for raw input data from the socket. */
106147005SdesBuffer input;
107147005Sdes
108147005Sdes/* Buffer for raw output data going to the socket. */
109147005SdesBuffer output;
110147005Sdes
111147005Sdes/* Buffer for the partial outgoing packet being constructed. */
112147005Sdesstatic Buffer outgoing_packet;
113147005Sdes
114147005Sdes/* Buffer for the incoming packet currently being processed. */
115147005Sdesstatic Buffer incoming_packet;
116147005Sdes
117147005Sdes/* Scratch buffer for packet compression/decompression. */
118147005Sdesstatic Buffer compression_buffer;
119147005Sdesstatic int compression_buffer_ready = 0;
120147005Sdes
121147005Sdes/* Flag indicating whether packet compression/decompression is enabled. */
122147005Sdesstatic int packet_compression = 0;
123147005Sdes
124147005Sdes/* default maximum packet size */
125147005Sdesu_int max_packet_size = 32768;
126147005Sdes
127147005Sdes/* Flag indicating whether this module has been initialized. */
128147005Sdesstatic int initialized = 0;
129147005Sdes
130147005Sdes/* Set to true if the connection is interactive. */
131147005Sdesstatic int interactive_mode = 0;
132147005Sdes
133147005Sdes/* Set to true if we are the server side. */
134147005Sdesstatic int server_side = 0;
135147005Sdes
136147005Sdes/* Set to true if we are authenticated. */
137147005Sdesstatic int after_authentication = 0;
138147005Sdes
139147005Sdesint keep_alive_timeouts = 0;
140147005Sdes
141147005Sdes/* Set to the maximum time that we will wait to send or receive a packet */
142147005Sdesstatic int packet_timeout_ms = -1;
143147005Sdes
144147005Sdes/* Session key information for Encryption and MAC */
145147005SdesNewkeys *newkeys[MODE_MAX];
146147005Sdesstatic struct packet_state {
14798937Sdes	u_int32_t seqnr;
14898937Sdes	u_int32_t packets;
14998937Sdes	u_int64_t blocks;
150162856Sdes	u_int64_t bytes;
151162856Sdes} p_read, p_send;
152162856Sdes
153162856Sdesstatic u_int64_t max_blocks_in, max_blocks_out;
154162856Sdesstatic u_int32_t rekey_limit;
155162856Sdes
156162856Sdes/* Session key for protocol v1 */
157162856Sdesstatic u_char ssh1_key[SSH_SESSION_KEY_LENGTH];
158162856Sdesstatic u_int ssh1_keylen;
159162856Sdes
160162856Sdes/* roundup current message to extra_pad bytes */
161162856Sdesstatic u_char extra_pad = 0;
162162856Sdes
163162856Sdesstruct packet {
164181111Sdes	TAILQ_ENTRY(packet) next;
165162856Sdes	u_char type;
166162856Sdes	Buffer payload;
167162856Sdes};
168162856SdesTAILQ_HEAD(, packet) outgoing;
169162856Sdes
17098937Sdes/*
17198937Sdes * Sets the descriptors used for communication.  Disables encryption until
17298937Sdes * packet_set_encryption_key is called.
17398937Sdes */
174147005Sdesvoid
175147005Sdespacket_set_connection(int fd_in, int fd_out)
176147005Sdes{
177147005Sdes	Cipher *none = cipher_by_name("none");
17898937Sdes
17998937Sdes	if (none == NULL)
180147005Sdes		fatal("packet_set_connection: cannot load cipher 'none'");
18198937Sdes	connection_in = fd_in;
18298937Sdes	connection_out = fd_out;
18398937Sdes	cipher_init(&send_context, none, (const u_char *)"",
18498937Sdes	    0, NULL, 0, CIPHER_ENCRYPT);
18598937Sdes	cipher_init(&receive_context, none, (const u_char *)"",
18698937Sdes	    0, NULL, 0, CIPHER_DECRYPT);
18798937Sdes	newkeys[MODE_IN] = newkeys[MODE_OUT] = NULL;
18898937Sdes	if (!initialized) {
18998937Sdes		initialized = 1;
19098937Sdes		buffer_init(&input);
19198937Sdes		buffer_init(&output);
19298937Sdes		buffer_init(&outgoing_packet);
19398937Sdes		buffer_init(&incoming_packet);
19498937Sdes		TAILQ_INIT(&outgoing);
19598937Sdes		p_send.packets = p_read.packets = 0;
19698937Sdes	}
19798937Sdes}
19898937Sdes
19998937Sdesvoid
20098937Sdespacket_set_timeout(int timeout, int count)
20198937Sdes{
20298937Sdes	if (timeout == 0 || count == 0) {
20398937Sdes		packet_timeout_ms = -1;
20498937Sdes		return;
20598937Sdes	}
206202213Sed	if ((INT_MAX / 1000) / count < timeout)
20798937Sdes		packet_timeout_ms = INT_MAX;
20898937Sdes	else
20998937Sdes		packet_timeout_ms = timeout * count * 1000;
210147005Sdes}
211147005Sdes
21298937Sdes/* Returns 1 if remote host is connected via socket, 0 if not. */
213147005Sdes
21498937Sdesint
21598937Sdespacket_connection_is_on_socket(void)
21698937Sdes{
21798937Sdes	struct sockaddr_storage from, to;
21898937Sdes	socklen_t fromlen, tolen;
219147005Sdes
220147005Sdes	/* filedescriptors in and out are the same, so it's a socket */
22198937Sdes	if (connection_in == connection_out)
22298937Sdes		return 1;
22398937Sdes	fromlen = sizeof(from);
22498937Sdes	memset(&from, 0, sizeof(from));
22598937Sdes	if (getpeername(connection_in, (struct sockaddr *)&from, &fromlen) < 0)
22698937Sdes		return 0;
22798937Sdes	tolen = sizeof(to);
22898937Sdes	memset(&to, 0, sizeof(to));
22998937Sdes	if (getpeername(connection_out, (struct sockaddr *)&to, &tolen) < 0)
230147005Sdes		return 0;
23198937Sdes	if (fromlen != tolen || memcmp(&from, &to, fromlen) != 0)
23298937Sdes		return 0;
233147005Sdes	if (from.ss_family != AF_INET && from.ss_family != AF_INET6)
23498937Sdes		return 0;
23598937Sdes	return 1;
23698937Sdes}
237147005Sdes
238147005Sdes/*
23998937Sdes * Exports an IV from the CipherContext required to export the key
24098937Sdes * state back from the unprivileged child to the privileged parent
24198937Sdes * process.
24298937Sdes */
24398937Sdes
24498937Sdesvoid
24598937Sdespacket_get_keyiv(int mode, u_char *iv, u_int len)
24698937Sdes{
24798937Sdes	CipherContext *cc;
24898937Sdes
24998937Sdes	if (mode == MODE_OUT)
250147005Sdes		cc = &send_context;
25198937Sdes	else
25298937Sdes		cc = &receive_context;
253147005Sdes
254147005Sdes	cipher_get_keyiv(cc, iv, len);
25598937Sdes}
25698937Sdes
25798937Sdesint
25898937Sdespacket_get_keycontext(int mode, u_char *dat)
25998937Sdes{
26098937Sdes	CipherContext *cc;
26198937Sdes
26298937Sdes	if (mode == MODE_OUT)
26398937Sdes		cc = &send_context;
26498937Sdes	else
26598937Sdes		cc = &receive_context;
26698937Sdes
26798937Sdes	return (cipher_get_keycontext(cc, dat));
26898937Sdes}
26998937Sdes
27098937Sdesvoid
27198937Sdespacket_set_keycontext(int mode, u_char *dat)
272221420Sdes{
27398937Sdes	CipherContext *cc;
27498937Sdes
27598937Sdes	if (mode == MODE_OUT)
27698937Sdes		cc = &send_context;
277147005Sdes	else
27898937Sdes		cc = &receive_context;
279147005Sdes
28098937Sdes	cipher_set_keycontext(cc, dat);
28198937Sdes}
282147005Sdes
283147005Sdesint
28498937Sdespacket_get_keyiv_len(int mode)
28598937Sdes{
28698937Sdes	CipherContext *cc;
28798937Sdes
28898937Sdes	if (mode == MODE_OUT)
28998937Sdes		cc = &send_context;
29098937Sdes	else
29198937Sdes		cc = &receive_context;
29298937Sdes
29398937Sdes	return (cipher_get_keyiv_len(cc));
29498937Sdes}
29598937Sdes
296221420Sdesvoid
29798937Sdespacket_set_iv(int mode, u_char *dat)
29898937Sdes{
29998937Sdes	CipherContext *cc;
30098937Sdes
30198937Sdes	if (mode == MODE_OUT)
30298937Sdes		cc = &send_context;
30398937Sdes	else
30498937Sdes		cc = &receive_context;
30598937Sdes
30698937Sdes	cipher_set_keyiv(cc, dat);
30798937Sdes}
30898937Sdes
30998937Sdesint
310221420Sdespacket_get_ssh1_cipher(void)
311221420Sdes{
31298937Sdes	return (cipher_get_number(receive_context.cipher));
31398937Sdes}
314147005Sdes
31598937Sdesvoid
31698937Sdespacket_get_state(int mode, u_int32_t *seqnr, u_int64_t *blocks, u_int32_t *packets,
31798937Sdes    u_int64_t *bytes)
318147005Sdes{
31998937Sdes	struct packet_state *state;
320147005Sdes
32198937Sdes	state = (mode == MODE_IN) ? &p_read : &p_send;
32298937Sdes	if (seqnr)
32398937Sdes		*seqnr = state->seqnr;
324147005Sdes	if (blocks)
325147005Sdes		*blocks = state->blocks;
32698937Sdes	if (packets)
32798937Sdes		*packets = state->packets;
32898937Sdes	if (bytes)
32998937Sdes		*bytes = state->bytes;
33098937Sdes}
33198937Sdes
33298937Sdesvoid
33398937Sdespacket_set_state(int mode, u_int32_t seqnr, u_int64_t blocks, u_int32_t packets,
33498937Sdes    u_int64_t bytes)
335221420Sdes{
336147005Sdes	struct packet_state *state;
33798937Sdes
33898937Sdes	state = (mode == MODE_IN) ? &p_read : &p_send;
33998937Sdes	state->seqnr = seqnr;
340147005Sdes	state->blocks = blocks;
341147005Sdes	state->packets = packets;
342147005Sdes	state->bytes = bytes;
34398937Sdes}
34498937Sdes
34598937Sdes/* returns 1 if connection is via ipv4 */
34698937Sdes
34798937Sdesint
34898937Sdespacket_connection_is_ipv4(void)
34998937Sdes{
350255767Sdes	struct sockaddr_storage to;
35198937Sdes	socklen_t tolen = sizeof(to);
35298937Sdes
35398937Sdes	memset(&to, 0, sizeof(to));
35498937Sdes	if (getsockname(connection_out, (struct sockaddr *)&to, &tolen) < 0)
35598937Sdes		return 0;
35698937Sdes	if (to.ss_family == AF_INET)
35798937Sdes		return 1;
35898937Sdes#ifdef IPV4_IN_IPV6
35998937Sdes	if (to.ss_family == AF_INET6 &&
36098937Sdes	    IN6_IS_ADDR_V4MAPPED(&((struct sockaddr_in6 *)&to)->sin6_addr))
36198937Sdes		return 1;
36298937Sdes#endif
363221420Sdes	return 0;
364147005Sdes}
36598937Sdes
36698937Sdes/* Sets the connection into non-blocking mode. */
36798937Sdes
36898937Sdesvoid
36998937Sdespacket_set_nonblocking(void)
37098937Sdes{
37198937Sdes	/* Set the socket into non-blocking mode. */
37298937Sdes	set_nonblock(connection_in);
37398937Sdes
37498937Sdes	if (connection_out != connection_in)
37598937Sdes		set_nonblock(connection_out);
37698937Sdes}
37798937Sdes
37898937Sdes/* Returns the socket used for reading. */
379147005Sdes
380149753Sdesint
381147005Sdespacket_get_connection_in(void)
382147005Sdes{
38398937Sdes	return connection_in;
38498937Sdes}
38598937Sdes
38698937Sdes/* Returns the descriptor used for writing. */
38798937Sdes
38898937Sdesint
389147005Sdespacket_get_connection_out(void)
39098937Sdes{
39198937Sdes	return connection_out;
392149753Sdes}
393147005Sdes
39498937Sdes/* Closes the connection and clears and frees internal data structures. */
39598937Sdes
39698937Sdesvoid
39798937Sdespacket_close(void)
39898937Sdes{
39998937Sdes	if (!initialized)
40098937Sdes		return;
40198937Sdes	initialized = 0;
40298937Sdes	if (connection_in == connection_out) {
40398937Sdes		shutdown(connection_out, SHUT_RDWR);
40498937Sdes		close(connection_out);
40598937Sdes	} else {
40698937Sdes		close(connection_in);
40798937Sdes		close(connection_out);
40898937Sdes	}
40998937Sdes	buffer_free(&input);
41098937Sdes	buffer_free(&output);
41198937Sdes	buffer_free(&outgoing_packet);
41298937Sdes	buffer_free(&incoming_packet);
413147005Sdes	if (compression_buffer_ready) {
41498937Sdes		buffer_free(&compression_buffer);
41598937Sdes		buffer_compress_uninit();
41698937Sdes	}
41798937Sdes	cipher_cleanup(&send_context);
41898937Sdes	cipher_cleanup(&receive_context);
41998937Sdes}
42098937Sdes
421147005Sdes/* Sets remote side protocol flags. */
42298937Sdes
42398937Sdesvoid
42498937Sdespacket_set_protocol_flags(u_int protocol_flags)
42598937Sdes{
42698937Sdes	remote_protocol_flags = protocol_flags;
42798937Sdes}
42898937Sdes
42998937Sdes/* Returns the remote protocol flags set earlier by the above function. */
430147005Sdes
43198937Sdesu_int
43298937Sdespacket_get_protocol_flags(void)
433147005Sdes{
434147005Sdes	return remote_protocol_flags;
435147005Sdes}
43698937Sdes
43798937Sdes/*
43898937Sdes * Starts packet compression from the next packet on in both directions.
43998937Sdes * Level is compression level 1 (fastest) - 9 (slow, best) as in gzip.
44098937Sdes */
44198937Sdes
44298937Sdesstatic void
44398937Sdespacket_init_compression(void)
44498937Sdes{
445147005Sdes	if (compression_buffer_ready == 1)
44698937Sdes		return;
44798937Sdes	compression_buffer_ready = 1;
44898937Sdes	buffer_init(&compression_buffer);
44998937Sdes}
45098937Sdes
45198937Sdesvoid
45298937Sdespacket_start_compression(int level)
45398937Sdes{
45498937Sdes	if (packet_compression && !compat20)
45598937Sdes		fatal("Compression already enabled.");
45698937Sdes	packet_compression = 1;
45798937Sdes	packet_init_compression();
45898937Sdes	buffer_compress_init_send(level);
45998937Sdes	buffer_compress_init_recv();
460137019Sdes}
461149753Sdes
462149753Sdes/*
463149753Sdes * Causes any further packets to be encrypted using the given key.  The same
464137019Sdes * key is used for both sending and reception.  However, both directions are
465137019Sdes * encrypted independently of each other.
466147005Sdes */
467147005Sdes
468221420Sdesvoid
469147005Sdespacket_set_encryption_key(const u_char *key, u_int keylen,
470221420Sdes    int number)
471147005Sdes{
472147005Sdes	Cipher *cipher = cipher_by_number(number);
47398937Sdes
47498937Sdes	if (cipher == NULL)
47598937Sdes		fatal("packet_set_encryption_key: unknown cipher number %d", number);
47698937Sdes	if (keylen < 20)
47798937Sdes		fatal("packet_set_encryption_key: keylen too small: %d", keylen);
47898937Sdes	if (keylen > SSH_SESSION_KEY_LENGTH)
479126277Sdes		fatal("packet_set_encryption_key: keylen too big: %d", keylen);
48098937Sdes	memcpy(ssh1_key, key, keylen);
48198937Sdes	ssh1_keylen = keylen;
48298937Sdes	cipher_init(&send_context, cipher, key, keylen, NULL, 0, CIPHER_ENCRYPT);
48398937Sdes	cipher_init(&receive_context, cipher, key, keylen, NULL, 0, CIPHER_DECRYPT);
48498937Sdes}
48598937Sdes
48698937Sdesu_int
48798937Sdespacket_get_encryption_key(u_char *key)
48898937Sdes{
48998937Sdes	if (key == NULL)
49098937Sdes		return (ssh1_keylen);
49198937Sdes	memcpy(key, ssh1_key, ssh1_keylen);
49298937Sdes	return (ssh1_keylen);
493147005Sdes}
49498937Sdes
49598937Sdes/* Start constructing a packet to send. */
49698937Sdesvoid
49798937Sdespacket_start(u_char type)
49898937Sdes{
49998937Sdes	u_char buf[9];
50098937Sdes	int len;
50198937Sdes
50298937Sdes	DBG(debug("packet_start[%d]", type));
50398937Sdes	len = compat20 ? 6 : 9;
50498937Sdes	memset(buf, 0, len - 1);
50598937Sdes	buf[len - 1] = type;
50698937Sdes	buffer_clear(&outgoing_packet);
50798937Sdes	buffer_append(&outgoing_packet, buf, len);
50898937Sdes}
509207319Sdes
510207319Sdes/* Append payload. */
511207319Sdesvoid
512207319Sdespacket_put_char(int value)
51398937Sdes{
514147005Sdes	char ch = value;
51598937Sdes
51698937Sdes	buffer_append(&outgoing_packet, &ch, 1);
517147005Sdes}
518147005Sdes
519147005Sdesvoid
52098937Sdespacket_put_int(u_int value)
52198937Sdes{
522147005Sdes	buffer_put_int(&outgoing_packet, value);
523147005Sdes}
52498937Sdes
52598937Sdesvoid
526147005Sdespacket_put_string(const void *buf, u_int len)
52798937Sdes{
528147005Sdes	buffer_put_string(&outgoing_packet, buf, len);
52998937Sdes}
53098937Sdes
53198937Sdesvoid
53298937Sdespacket_put_cstring(const char *str)
53398937Sdes{
53498937Sdes	buffer_put_cstring(&outgoing_packet, str);
53598937Sdes}
53698937Sdes
53798937Sdesvoid
53898937Sdespacket_put_raw(const void *buf, u_int len)
53998937Sdes{
54098937Sdes	buffer_append(&outgoing_packet, buf, len);
54198937Sdes}
54298937Sdes
54398937Sdesvoid
54498937Sdespacket_put_bignum(BIGNUM * value)
54598937Sdes{
54698937Sdes	buffer_put_bignum(&outgoing_packet, value);
54798937Sdes}
54898937Sdes
54998937Sdesvoid
55098937Sdespacket_put_bignum2(BIGNUM * value)
55198937Sdes{
552147005Sdes	buffer_put_bignum2(&outgoing_packet, value);
553147005Sdes}
554147005Sdes
555147005Sdes/*
55698937Sdes * Finalizes and sends the packet.  If the encryption key has been set,
557149753Sdes * encrypts the packet before sending.
55898937Sdes */
55998937Sdes
560147005Sdesstatic void
56198937Sdespacket_send1(void)
562147005Sdes{
56398937Sdes	u_char buf[8], *cp;
56498937Sdes	int i, padding, len;
56598937Sdes	u_int checksum;
566147005Sdes	u_int32_t rnd = 0;
56798937Sdes
56898937Sdes	/*
56998937Sdes	 * If using packet compression, compress the payload of the outgoing
57098937Sdes	 * packet.
57198937Sdes	 */
57298937Sdes	if (packet_compression) {
57398937Sdes		buffer_clear(&compression_buffer);
57498937Sdes		/* Skip padding. */
57598937Sdes		buffer_consume(&outgoing_packet, 8);
57698937Sdes		/* padding */
57798937Sdes		buffer_append(&compression_buffer, "\0\0\0\0\0\0\0\0", 8);
578147005Sdes		buffer_compress(&outgoing_packet, &compression_buffer);
57998937Sdes		buffer_clear(&outgoing_packet);
58098937Sdes		buffer_append(&outgoing_packet, buffer_ptr(&compression_buffer),
581149753Sdes		    buffer_len(&compression_buffer));
582147005Sdes	}
58398937Sdes	/* Compute packet length without padding (add checksum, remove padding). */
58498937Sdes	len = buffer_len(&outgoing_packet) + 4 - 8;
58598937Sdes
58698937Sdes	/* Insert padding. Initialized to zero in packet_start1() */
587147005Sdes	padding = 8 - len % 8;
588147005Sdes	if (!send_context.plaintext) {
58998937Sdes		cp = buffer_ptr(&outgoing_packet);
59098937Sdes		for (i = 0; i < padding; i++) {
59198937Sdes			if (i % 4 == 0)
59298937Sdes				rnd = arc4random();
59398937Sdes			cp[7 - i] = rnd & 0xff;
59498937Sdes			rnd >>= 8;
59598937Sdes		}
59698937Sdes	}
59798937Sdes	buffer_consume(&outgoing_packet, 8 - padding);
59898937Sdes
59998937Sdes	/* Add check bytes. */
60098937Sdes	checksum = ssh_crc32(buffer_ptr(&outgoing_packet),
60198937Sdes	    buffer_len(&outgoing_packet));
60298937Sdes	put_u32(buf, checksum);
60398937Sdes	buffer_append(&outgoing_packet, buf, 4);
60498937Sdes
60598937Sdes#ifdef PACKET_DEBUG
60698937Sdes	fprintf(stderr, "packet_send plain: ");
60798937Sdes	buffer_dump(&outgoing_packet);
60898937Sdes#endif
60998937Sdes
61098937Sdes	/* Append to output. */
61198937Sdes	put_u32(buf, len);
61298937Sdes	buffer_append(&output, buf, 4);
61398937Sdes	cp = buffer_append_space(&output, buffer_len(&outgoing_packet));
61498937Sdes	cipher_crypt(&send_context, cp, buffer_ptr(&outgoing_packet),
615147005Sdes	    buffer_len(&outgoing_packet));
61698937Sdes
61798937Sdes#ifdef PACKET_DEBUG
61898937Sdes	fprintf(stderr, "encrypted: ");
61998937Sdes	buffer_dump(&output);
62098937Sdes#endif
62198937Sdes	p_send.packets++;
62298937Sdes	p_send.bytes += len + buffer_len(&outgoing_packet);
62398937Sdes	buffer_clear(&outgoing_packet);
62498937Sdes
62598937Sdes	/*
62698937Sdes	 * Note that the packet is now only buffered in output.  It won't be
62798937Sdes	 * actually sent until packet_write_wait or packet_write_poll is
62898937Sdes	 * called.
62998937Sdes	 */
63098937Sdes}
631147005Sdes
63298937Sdesvoid
63398937Sdesset_newkeys(int mode)
634147005Sdes{
63598937Sdes	Enc *enc;
63698937Sdes	Mac *mac;
63798937Sdes	Comp *comp;
63898937Sdes	CipherContext *cc;
63998937Sdes	u_int64_t *max_blocks;
64098937Sdes	int crypt_type;
64198937Sdes
64298937Sdes	debug2("set_newkeys: mode %d", mode);
643113911Sdes
644113911Sdes	if (mode == MODE_OUT) {
645147005Sdes		cc = &send_context;
646147005Sdes		crypt_type = CIPHER_ENCRYPT;
64798937Sdes		p_send.packets = p_send.blocks = 0;
64898937Sdes		max_blocks = &max_blocks_out;
64998937Sdes	} else {
65098937Sdes		cc = &receive_context;
65198937Sdes		crypt_type = CIPHER_DECRYPT;
65298937Sdes		p_read.packets = p_read.blocks = 0;
65398937Sdes		max_blocks = &max_blocks_in;
65498937Sdes	}
65598937Sdes	if (newkeys[mode] != NULL) {
65698937Sdes		debug("set_newkeys: rekeying");
65798937Sdes		cipher_cleanup(cc);
65898937Sdes		enc  = &newkeys[mode]->enc;
65998937Sdes		mac  = &newkeys[mode]->mac;
660106130Sdes		comp = &newkeys[mode]->comp;
66198937Sdes		mac_clear(mac);
66298937Sdes		xfree(enc->name);
66398937Sdes		xfree(enc->iv);
66498937Sdes		xfree(enc->key);
66598937Sdes		xfree(mac->name);
666106130Sdes		xfree(mac->key);
66798937Sdes		xfree(comp->name);
66898937Sdes		xfree(newkeys[mode]);
66998937Sdes	}
67098937Sdes	newkeys[mode] = kex_get_newkeys(mode);
67198937Sdes	if (newkeys[mode] == NULL)
67298937Sdes		fatal("newkeys: no keys for mode %d", mode);
67398937Sdes	enc  = &newkeys[mode]->enc;
67498937Sdes	mac  = &newkeys[mode]->mac;
67598937Sdes	comp = &newkeys[mode]->comp;
67698937Sdes	if (mac_init(mac) == 0)
67798937Sdes		mac->enabled = 1;
67898937Sdes	DBG(debug("cipher_init_context: %d", mode));
67998937Sdes	cipher_init(cc, enc->cipher, enc->key, enc->key_len,
68098937Sdes	    enc->iv, enc->block_size, crypt_type);
68198937Sdes	/* Deleting the keys does not gain extra security */
682147005Sdes	/* memset(enc->iv,  0, enc->block_size);
68398937Sdes	   memset(enc->key, 0, enc->key_len);
68498937Sdes	   memset(mac->key, 0, mac->key_len); */
68598937Sdes	if ((comp->type == COMP_ZLIB ||
68698937Sdes	    (comp->type == COMP_DELAYED && after_authentication)) &&
68798937Sdes	    comp->enabled == 0) {
68898937Sdes		packet_init_compression();
68998937Sdes		if (mode == MODE_OUT)
690147005Sdes			buffer_compress_init_send(6);
691147005Sdes		else
69298937Sdes			buffer_compress_init_recv();
693184122Sdes		comp->enabled = 1;
694184122Sdes	}
69598937Sdes	/*
69698937Sdes	 * The 2^(blocksize*2) limit is too expensive for 3DES,
69798937Sdes	 * blowfish, etc, so enforce a 1GB limit for small blocksizes.
69898937Sdes	 */
69998937Sdes	if (enc->block_size >= 16)
70098937Sdes		*max_blocks = (u_int64_t)1 << (enc->block_size*2);
701113911Sdes	else
702113911Sdes		*max_blocks = ((u_int64_t)1 << 30) / enc->block_size;
703113911Sdes	if (rekey_limit)
704113911Sdes		*max_blocks = MIN(*max_blocks, rekey_limit / enc->block_size);
705113911Sdes}
706113911Sdes
707113911Sdes/*
708113911Sdes * Delayed compression for SSH2 is enabled after authentication:
709113911Sdes * This happens on the server side after a SSH2_MSG_USERAUTH_SUCCESS is sent,
710113911Sdes * and on the client side after a SSH2_MSG_USERAUTH_SUCCESS is received.
711113911Sdes */
712113911Sdesstatic void
713113911Sdespacket_enable_delayed_compress(void)
71498937Sdes{
71598937Sdes	Comp *comp = NULL;
71698937Sdes	int mode;
71798937Sdes
71898937Sdes	/*
71998937Sdes	 * Remember that we are past the authentication step, so rekeying
72098937Sdes	 * with COMP_DELAYED will turn on compression immediately.
72198937Sdes	 */
72298937Sdes	after_authentication = 1;
72398937Sdes	for (mode = 0; mode < MODE_MAX; mode++) {
72498937Sdes		/* protocol error: USERAUTH_SUCCESS received before NEWKEYS */
72598937Sdes		if (newkeys[mode] == NULL)
72698937Sdes			continue;
72798937Sdes		comp = &newkeys[mode]->comp;
72898937Sdes		if (comp && !comp->enabled && comp->type == COMP_DELAYED) {
729147005Sdes			packet_init_compression();
73098937Sdes			if (mode == MODE_OUT)
73198937Sdes				buffer_compress_init_send(6);
732147005Sdes			else
73398937Sdes				buffer_compress_init_recv();
734147005Sdes			comp->enabled = 1;
73598937Sdes		}
73698937Sdes	}
73798937Sdes}
73898937Sdes
73998937Sdes/*
740113911Sdes * Finalize packet in SSH2 format (compress, mac, encrypt, enqueue)
741113911Sdes */
742113911Sdesstatic void
74398937Sdespacket_send2_wrapped(void)
744147005Sdes{
74598937Sdes	u_char type, *cp, *macbuf = NULL;
74698937Sdes	u_char padlen, pad;
74798937Sdes	u_int packet_length = 0;
74898937Sdes	u_int i, len;
74998937Sdes	u_int32_t rnd = 0;
75098937Sdes	Enc *enc   = NULL;
75198937Sdes	Mac *mac   = NULL;
75298937Sdes	Comp *comp = NULL;
75398937Sdes	int block_size;
75498937Sdes
75598937Sdes	if (newkeys[MODE_OUT] != NULL) {
75698937Sdes		enc  = &newkeys[MODE_OUT]->enc;
75798937Sdes		mac  = &newkeys[MODE_OUT]->mac;
75898937Sdes		comp = &newkeys[MODE_OUT]->comp;
75998937Sdes	}
76098937Sdes	block_size = enc ? enc->block_size : 8;
761147005Sdes
76298937Sdes	cp = buffer_ptr(&outgoing_packet);
763202213Sed	type = cp[5];
764202213Sed
76598937Sdes#ifdef PACKET_DEBUG
76698937Sdes	fprintf(stderr, "plain:     ");
76798937Sdes	buffer_dump(&outgoing_packet);
76898937Sdes#endif
76998937Sdes
77098937Sdes	if (comp && comp->enabled) {
77198937Sdes		len = buffer_len(&outgoing_packet);
77298937Sdes		/* skip header, compress only payload */
77398937Sdes		buffer_consume(&outgoing_packet, 5);
77498937Sdes		buffer_clear(&compression_buffer);
775147005Sdes		buffer_compress(&outgoing_packet, &compression_buffer);
776147005Sdes		buffer_clear(&outgoing_packet);
77798937Sdes		buffer_append(&outgoing_packet, "\0\0\0\0\0", 5);
77898937Sdes		buffer_append(&outgoing_packet, buffer_ptr(&compression_buffer),
77998937Sdes		    buffer_len(&compression_buffer));
78098937Sdes		DBG(debug("compression: raw %d compressed %d", len,
78198937Sdes		    buffer_len(&outgoing_packet)));
78298937Sdes	}
783113911Sdes
784113911Sdes	/* sizeof (packet_len + pad_len + payload) */
785113911Sdes	len = buffer_len(&outgoing_packet);
786113911Sdes
787113911Sdes	/*
788113911Sdes	 * calc size of padding, alloc space, get random data,
789113911Sdes	 * minimum padding is 4 bytes
790113911Sdes	 */
791113911Sdes	padlen = block_size - (len % block_size);
792113911Sdes	if (padlen < 4)
793113911Sdes		padlen += block_size;
794113911Sdes	if (extra_pad) {
795113911Sdes		/* will wrap if extra_pad+padlen > 255 */
79698937Sdes		extra_pad  = roundup(extra_pad, block_size);
79798937Sdes		pad = extra_pad - ((len + padlen) % extra_pad);
79898937Sdes		debug3("packet_send2: adding %d (len %d padlen %d extra_pad %d)",
79998937Sdes		    pad, len, padlen, extra_pad);
80098937Sdes		padlen += pad;
80198937Sdes		extra_pad = 0;
80298937Sdes	}
80398937Sdes	cp = buffer_append_space(&outgoing_packet, padlen);
80498937Sdes	if (enc && !send_context.plaintext) {
80598937Sdes		/* random padding */
80698937Sdes		for (i = 0; i < padlen; i++) {
80798937Sdes			if (i % 4 == 0)
80898937Sdes				rnd = arc4random();
80998937Sdes			cp[i] = rnd & 0xff;
81098937Sdes			rnd >>= 8;
81198937Sdes		}
81298937Sdes	} else {
81398937Sdes		/* clear padding */
81498937Sdes		memset(cp, 0, padlen);
81598937Sdes	}
81698937Sdes	/* packet_length includes payload, padding and padding length field */
81798937Sdes	packet_length = buffer_len(&outgoing_packet) - 4;
81898937Sdes	cp = buffer_ptr(&outgoing_packet);
81998937Sdes	put_u32(cp, packet_length);
82098937Sdes	cp[4] = padlen;
82198937Sdes	DBG(debug("send: len %d (includes padlen %d)", packet_length+4, padlen));
82298937Sdes
82398937Sdes	/* compute MAC over seqnr and packet(length fields, payload, padding) */
82498937Sdes	if (mac && mac->enabled) {
82598937Sdes		macbuf = mac_compute(mac, p_send.seqnr,
82698937Sdes		    buffer_ptr(&outgoing_packet),
827147005Sdes		    buffer_len(&outgoing_packet));
82898937Sdes		DBG(debug("done calc MAC out #%d", p_send.seqnr));
82998937Sdes	}
83098937Sdes	/* encrypt packet and append to output buffer. */
831149753Sdes	cp = buffer_append_space(&output, buffer_len(&outgoing_packet));
832147005Sdes	cipher_crypt(&send_context, cp, buffer_ptr(&outgoing_packet),
833147005Sdes	    buffer_len(&outgoing_packet));
834147005Sdes	/* append unencrypted MAC */
83598937Sdes	if (mac && mac->enabled)
83698937Sdes		buffer_append(&output, macbuf, mac->mac_len);
83798937Sdes#ifdef PACKET_DEBUG
83898937Sdes	fprintf(stderr, "encrypted: ");
83998937Sdes	buffer_dump(&output);
84098937Sdes#endif
84198937Sdes	/* increment sequence number for outgoing packets */
84298937Sdes	if (++p_send.seqnr == 0)
84398937Sdes		logit("outgoing seqnr wraps around");
84498937Sdes	if (++p_send.packets == 0)
845147005Sdes		if (!(datafellows & SSH_BUG_NOREKEY))
84698937Sdes			fatal("XXX too many packets with same key");
84798937Sdes	p_send.blocks += (packet_length + 4) / block_size;
84898937Sdes	p_send.bytes += packet_length + 4;
849147005Sdes	buffer_clear(&outgoing_packet);
85098937Sdes
85198937Sdes	if (type == SSH2_MSG_NEWKEYS)
85298937Sdes		set_newkeys(MODE_OUT);
85398937Sdes	else if (type == SSH2_MSG_USERAUTH_SUCCESS && server_side)
85498937Sdes		packet_enable_delayed_compress();
85598937Sdes}
856147005Sdes
857137019Sdesstatic void
858137019Sdespacket_send2(void)
85998937Sdes{
86098937Sdes	static int rekeying = 0;
86198937Sdes	struct packet *p;
86298937Sdes	u_char type, *cp;
86398937Sdes
86498937Sdes	cp = buffer_ptr(&outgoing_packet);
86598937Sdes	type = cp[5];
86698937Sdes
867137019Sdes	/* during rekeying we can only send key exchange messages */
868137019Sdes	if (rekeying) {
869137019Sdes		if (!((type >= SSH2_MSG_TRANSPORT_MIN) &&
870137019Sdes		    (type <= SSH2_MSG_TRANSPORT_MAX))) {
871147005Sdes			debug("enqueue packet: %u", type);
872221420Sdes			p = xmalloc(sizeof(*p));
873137019Sdes			p->type = type;
874137019Sdes			memcpy(&p->payload, &outgoing_packet, sizeof(Buffer));
875137019Sdes			buffer_init(&outgoing_packet);
876149753Sdes			TAILQ_INSERT_TAIL(&outgoing, p, next);
877147005Sdes			return;
878221420Sdes		}
879137019Sdes	}
880137019Sdes
88198937Sdes	/* rekeying starts with sending KEXINIT */
88298937Sdes	if (type == SSH2_MSG_KEXINIT)
88398937Sdes		rekeying = 1;
88498937Sdes
88598937Sdes	packet_send2_wrapped();
88698937Sdes
887147005Sdes	/* after a NEWKEYS message we can send the complete queue */
888147005Sdes	if (type == SSH2_MSG_NEWKEYS) {
889147005Sdes		rekeying = 0;
890147005Sdes		while ((p = TAILQ_FIRST(&outgoing))) {
89198937Sdes			type = p->type;
892137019Sdes			debug("dequeue packet: %u", type);
893147005Sdes			buffer_free(&outgoing_packet);
894221420Sdes			memcpy(&outgoing_packet, &p->payload,
895137019Sdes			    sizeof(Buffer));
896137019Sdes			TAILQ_REMOVE(&outgoing, p, next);
897137019Sdes			xfree(p);
898147005Sdes			packet_send2_wrapped();
899137019Sdes		}
900221420Sdes	}
901137019Sdes}
902137019Sdes
903147005Sdesvoid
904137019Sdespacket_send(void)
90598937Sdes{
906221420Sdes	if (compat20)
907221420Sdes		packet_send2();
908147005Sdes	else
90998937Sdes		packet_send1();
910147005Sdes	DBG(debug("packet_send done"));
911147005Sdes}
91298937Sdes
913147005Sdes/*
91498937Sdes * Waits until a packet has been received, and returns its type.  Note that
91598937Sdes * no other data is processed until this returns, so this function should not
91698937Sdes * be used during the interactive session.
91798937Sdes */
91898937Sdes
91998937Sdesint
92098937Sdespacket_read_seqnr(u_int32_t *seqnr_p)
92198937Sdes{
92298937Sdes	int type, len, ret, ms_remain;
92398937Sdes	fd_set *setp;
92498937Sdes	char buf[8192];
92598937Sdes	struct timeval timeout, start, *timeoutp = NULL;
926147005Sdes
927147005Sdes	DBG(debug("packet_read()"));
92898937Sdes
92998937Sdes	setp = (fd_set *)xcalloc(howmany(connection_in+1, NFDBITS),
93098937Sdes	    sizeof(fd_mask));
931147005Sdes
932147005Sdes	/* Since we are blocking, ensure that all written packets have been sent. */
93398937Sdes	packet_write_wait();
93498937Sdes
935147005Sdes	/* Stay in the loop until we have received a complete packet. */
93698937Sdes	for (;;) {
93798937Sdes		/* Try to read a packet from the buffer. */
93898937Sdes		type = packet_read_poll_seqnr(seqnr_p);
93998937Sdes		if (!compat20 && (
94098937Sdes		    type == SSH_SMSG_SUCCESS
94198937Sdes		    || type == SSH_SMSG_FAILURE
94298937Sdes		    || type == SSH_CMSG_EOF
94398937Sdes		    || type == SSH_CMSG_EXIT_CONFIRMATION))
94498937Sdes			packet_check_eom();
94598937Sdes		/* If we got a packet, return it. */
94698937Sdes		if (type != SSH_MSG_NONE) {
947147005Sdes			xfree(setp);
948147005Sdes			return type;
94998937Sdes		}
95098937Sdes		/*
95198937Sdes		 * Otherwise, wait for some data to arrive, add it to the
952147005Sdes		 * buffer, and try again.
953147005Sdes		 */
95498937Sdes		memset(setp, 0, howmany(connection_in + 1, NFDBITS) *
95598937Sdes		    sizeof(fd_mask));
956147005Sdes		FD_SET(connection_in, setp);
95798937Sdes
95898937Sdes		if (packet_timeout_ms > 0) {
95998937Sdes			ms_remain = packet_timeout_ms;
96098937Sdes			timeoutp = &timeout;
96198937Sdes		}
96298937Sdes		/* Wait for some data to arrive. */
96398937Sdes		for (;;) {
96498937Sdes			if (packet_timeout_ms != -1) {
965147005Sdes				ms_to_timeval(&timeout, ms_remain);
96698937Sdes				gettimeofday(&start, NULL);
96798937Sdes			}
968147005Sdes			if ((ret = select(connection_in + 1, setp, NULL,
96998937Sdes			    NULL, timeoutp)) >= 0)
97098937Sdes				break;
971147005Sdes		   	if (errno != EAGAIN && errno != EINTR &&
972147005Sdes			    errno != EWOULDBLOCK)
97398937Sdes				break;
97498937Sdes			if (packet_timeout_ms == -1)
97598937Sdes				continue;
97698937Sdes			ms_subtract_diff(&start, &ms_remain);
97798937Sdes			if (ms_remain <= 0) {
97898937Sdes				ret = 0;
97998937Sdes				break;
98098937Sdes			}
98198937Sdes		}
98298937Sdes		if (ret == 0) {
98398937Sdes			logit("Connection to %.200s timed out while "
98498937Sdes			    "waiting to read", get_remote_ipaddr());
98598937Sdes			cleanup_exit(255);
98698937Sdes		}
98798937Sdes		/* Read data from the socket. */
98898937Sdes		len = read(connection_in, buf, sizeof(buf));
98998937Sdes		if (len == 0) {
99098937Sdes			logit("Connection closed by %.200s", get_remote_ipaddr());
99198937Sdes			cleanup_exit(255);
99298937Sdes		}
99398937Sdes		if (len < 0)
99498937Sdes			fatal("Read from socket failed: %.100s", strerror(errno));
99598937Sdes		/* Append it to the buffer. */
99698937Sdes		packet_process_incoming(buf, len);
99798937Sdes	}
99898937Sdes	/* NOTREACHED */
99998937Sdes}
100098937Sdes
100198937Sdesint
100298937Sdespacket_read(void)
1003147005Sdes{
100498937Sdes	return packet_read_seqnr(NULL);
100598937Sdes}
100698937Sdes
100798937Sdes/*
100898937Sdes * Waits until a packet has been received, verifies that its type matches
100998937Sdes * that given, and gives a fatal error and exits if there is a mismatch.
101098937Sdes */
101198937Sdes
1012147005Sdesvoid
1013147005Sdespacket_read_expect(int expected_type)
101498937Sdes{
101598937Sdes	int type;
101698937Sdes
101798937Sdes	type = packet_read();
101898937Sdes	if (type != expected_type)
101998937Sdes		packet_disconnect("Protocol error: expected packet type %d, got %d",
102098937Sdes		    expected_type, type);
102198937Sdes}
102298937Sdes
102398937Sdes/* Checks if a full packet is available in the data received so far via
102498937Sdes * packet_process_incoming.  If so, reads the packet; otherwise returns
1025147005Sdes * SSH_MSG_NONE.  This does not wait for data from the connection.
1026147005Sdes *
102798937Sdes * SSH_MSG_DISCONNECT is handled specially here.  Also,
102898937Sdes * SSH_MSG_IGNORE messages are skipped by this function and are never returned
102998937Sdes * to higher levels.
1030147005Sdes */
1031147005Sdes
103298937Sdesstatic int
103398937Sdespacket_read_poll1(void)
1034147005Sdes{
103598937Sdes	u_int len, padded_len;
103698937Sdes	u_char *cp, type;
103798937Sdes	u_int checksum, stored_checksum;
103898937Sdes
103998937Sdes	/* Check if input size is less than minimum packet size. */
104098937Sdes	if (buffer_len(&input) < 4 + 8)
104198937Sdes		return SSH_MSG_NONE;
104298937Sdes	/* Get length of incoming packet. */
104398937Sdes	cp = buffer_ptr(&input);
104498937Sdes	len = get_u32(cp);
104598937Sdes	if (len < 1 + 2 + 2 || len > 256 * 1024)
104698937Sdes		packet_disconnect("Bad packet length %u.", len);
104798937Sdes	padded_len = (len + 8) & ~7;
104898937Sdes
104998937Sdes	/* Check if the packet has been entirely received. */
105098937Sdes	if (buffer_len(&input) < 4 + padded_len)
105198937Sdes		return SSH_MSG_NONE;
105298937Sdes
105398937Sdes	/* The entire packet is in buffer. */
105498937Sdes
105598937Sdes	/* Consume packet length. */
1056147005Sdes	buffer_consume(&input, 4);
105798937Sdes
105898937Sdes	/*
105998937Sdes	 * Cryptographic attack detector for ssh
106098937Sdes	 * (C)1998 CORE-SDI, Buenos Aires Argentina
106198937Sdes	 * Ariel Futoransky(futo@core-sdi.com)
106298937Sdes	 */
106398937Sdes	if (!receive_context.plaintext) {
1064147005Sdes		switch (detect_attack(buffer_ptr(&input), padded_len)) {
106598937Sdes		case DEATTACK_DETECTED:
1066147005Sdes			packet_disconnect("crc32 compensation attack: "
106798937Sdes			    "network attack detected");
1068147005Sdes		case DEATTACK_DOS_DETECTED:
1069147005Sdes			packet_disconnect("deattack denial of "
107098937Sdes			    "service detected");
107198937Sdes		}
107298937Sdes	}
107398937Sdes
107498937Sdes	/* Decrypt data to incoming_packet. */
107598937Sdes	buffer_clear(&incoming_packet);
107698937Sdes	cp = buffer_append_space(&incoming_packet, padded_len);
107798937Sdes	cipher_crypt(&receive_context, cp, buffer_ptr(&input), padded_len);
107898937Sdes
107998937Sdes	buffer_consume(&input, padded_len);
108098937Sdes
1081149753Sdes#ifdef PACKET_DEBUG
1082147005Sdes	fprintf(stderr, "read_poll plain: ");
1083147005Sdes	buffer_dump(&incoming_packet);
1084147005Sdes#endif
108598937Sdes
108698937Sdes	/* Compute packet checksum. */
108798937Sdes	checksum = ssh_crc32(buffer_ptr(&incoming_packet),
108898937Sdes	    buffer_len(&incoming_packet) - 4);
108998937Sdes
109098937Sdes	/* Skip padding. */
109198937Sdes	buffer_consume(&incoming_packet, 8 - len % 8);
1092147005Sdes
109398937Sdes	/* Test check bytes. */
1094147005Sdes	if (len != buffer_len(&incoming_packet))
109598937Sdes		packet_disconnect("packet_read_poll1: len %d != buffer_len %d.",
109698937Sdes		    len, buffer_len(&incoming_packet));
1097124211Sdes
109898937Sdes	cp = (u_char *)buffer_ptr(&incoming_packet) + len - 4;
1099147005Sdes	stored_checksum = get_u32(cp);
110098937Sdes	if (checksum != stored_checksum)
110198937Sdes		packet_disconnect("Corrupted check bytes on input.");
110298937Sdes	buffer_consume_end(&incoming_packet, 4);
1103147005Sdes
1104147005Sdes	if (packet_compression) {
110598937Sdes		buffer_clear(&compression_buffer);
110698937Sdes		buffer_uncompress(&incoming_packet, &compression_buffer);
110798937Sdes		buffer_clear(&incoming_packet);
110898937Sdes		buffer_append(&incoming_packet, buffer_ptr(&compression_buffer),
110998937Sdes		    buffer_len(&compression_buffer));
111098937Sdes	}
111198937Sdes	p_read.packets++;
111298937Sdes	p_read.bytes += padded_len + 4;
1113147005Sdes	type = buffer_get_char(&incoming_packet);
111498937Sdes	if (type < SSH_MSG_MIN || type > SSH_MSG_MAX)
111598937Sdes		packet_disconnect("Invalid ssh1 packet type: %d", type);
111698937Sdes	return type;
111798937Sdes}
111898937Sdes
111998937Sdesstatic int
112098937Sdespacket_read_poll2(u_int32_t *seqnr_p)
112198937Sdes{
112298937Sdes	static u_int packet_length = 0;
1123147005Sdes	u_int padlen, need;
112498937Sdes	u_char *macbuf, *cp, type;
112598937Sdes	u_int maclen, block_size;
112698937Sdes	Enc *enc   = NULL;
112798937Sdes	Mac *mac   = NULL;
112898937Sdes	Comp *comp = NULL;
112998937Sdes
113098937Sdes	if (newkeys[MODE_IN] != NULL) {
113198937Sdes		enc  = &newkeys[MODE_IN]->enc;
1132147005Sdes		mac  = &newkeys[MODE_IN]->mac;
113398937Sdes		comp = &newkeys[MODE_IN]->comp;
1134147005Sdes	}
113598937Sdes	maclen = mac && mac->enabled ? mac->mac_len : 0;
1136147005Sdes	block_size = enc ? enc->block_size : 8;
1137147005Sdes
113898937Sdes	if (packet_length == 0) {
113998937Sdes		/*
114098937Sdes		 * check if input size is less than the cipher block size,
114198937Sdes		 * decrypt first block and extract length of incoming packet
1142149753Sdes		 */
1143147005Sdes		if (buffer_len(&input) < block_size)
114498937Sdes			return SSH_MSG_NONE;
114598937Sdes		buffer_clear(&incoming_packet);
114698937Sdes		cp = buffer_append_space(&incoming_packet, block_size);
114798937Sdes		cipher_crypt(&receive_context, cp, buffer_ptr(&input),
114898937Sdes		    block_size);
114998937Sdes		cp = buffer_ptr(&incoming_packet);
115098937Sdes		packet_length = get_u32(cp);
115198937Sdes		if (packet_length < 1 + 4 || packet_length > 256 * 1024) {
115298937Sdes#ifdef PACKET_DEBUG
115398937Sdes			buffer_dump(&incoming_packet);
115498937Sdes#endif
115598937Sdes			packet_disconnect("Bad packet length %u.", packet_length);
115698937Sdes		}
115798937Sdes		DBG(debug("input: packet len %u", packet_length+4));
115898937Sdes		buffer_consume(&input, block_size);
115998937Sdes	}
116098937Sdes	/* we have a partial packet of block_size bytes */
116198937Sdes	need = 4 + packet_length - block_size;
116298937Sdes	DBG(debug("partial packet %d, need %d, maclen %d", block_size,
116398937Sdes	    need, maclen));
1164147005Sdes	if (need % block_size != 0)
116598937Sdes		fatal("padding error: need %d block %d mod %d",
116698937Sdes		    need, block_size, need % block_size);
1167147005Sdes	/*
116898937Sdes	 * check if the entire packet has been received and
1169147005Sdes	 * decrypt into incoming_packet
117098937Sdes	 */
117198937Sdes	if (buffer_len(&input) < need + maclen)
1172147005Sdes		return SSH_MSG_NONE;
117398937Sdes#ifdef PACKET_DEBUG
117498937Sdes	fprintf(stderr, "read_poll enc/full: ");
117598937Sdes	buffer_dump(&input);
117698937Sdes#endif
117798937Sdes	cp = buffer_append_space(&incoming_packet, need);
117898937Sdes	cipher_crypt(&receive_context, cp, buffer_ptr(&input), need);
117998937Sdes	buffer_consume(&input, need);
1180147005Sdes	/*
118198937Sdes	 * compute MAC over seqnr and packet,
118298937Sdes	 * increment sequence number for incoming packet
118398937Sdes	 */
118498937Sdes	if (mac && mac->enabled) {
118598937Sdes		macbuf = mac_compute(mac, p_read.seqnr,
1186149753Sdes		    buffer_ptr(&incoming_packet),
118798937Sdes		    buffer_len(&incoming_packet));
1188147005Sdes		if (memcmp(macbuf, buffer_ptr(&input), mac->mac_len) != 0)
118998937Sdes			packet_disconnect("Corrupted MAC on input.");
119098937Sdes		DBG(debug("MAC #%d ok", p_read.seqnr));
1191149753Sdes		buffer_consume(&input, mac->mac_len);
119298937Sdes	}
119398937Sdes	if (seqnr_p != NULL)
1194147005Sdes		*seqnr_p = p_read.seqnr;
119598937Sdes	if (++p_read.seqnr == 0)
119698937Sdes		logit("incoming seqnr wraps around");
119798937Sdes	if (++p_read.packets == 0)
119898937Sdes		if (!(datafellows & SSH_BUG_NOREKEY))
119998937Sdes			fatal("XXX too many packets with same key");
120098937Sdes	p_read.blocks += (packet_length + 4) / block_size;
1201147005Sdes	p_read.bytes += packet_length + 4;
120298937Sdes
120398937Sdes	/* get padlen */
120498937Sdes	cp = buffer_ptr(&incoming_packet);
120598937Sdes	padlen = cp[4];
1206149753Sdes	DBG(debug("input: padlen %d", padlen));
120798937Sdes	if (padlen < 4)
120898937Sdes		packet_disconnect("Corrupted padlen %d on input.", padlen);
1209147005Sdes
121098937Sdes	/* skip packet size + padlen, discard padding */
1211221420Sdes	buffer_consume(&incoming_packet, 4 + 1);
121298937Sdes	buffer_consume_end(&incoming_packet, padlen);
1213147005Sdes
1214147005Sdes	DBG(debug("input: len before de-compress %d", buffer_len(&incoming_packet)));
1215147005Sdes	if (comp && comp->enabled) {
1216147005Sdes		buffer_clear(&compression_buffer);
121798937Sdes		buffer_uncompress(&incoming_packet, &compression_buffer);
121898937Sdes		buffer_clear(&incoming_packet);
121998937Sdes		buffer_append(&incoming_packet, buffer_ptr(&compression_buffer),
122098937Sdes		    buffer_len(&compression_buffer));
122198937Sdes		DBG(debug("input: len after de-compress %d",
122298937Sdes		    buffer_len(&incoming_packet)));
122398937Sdes	}
122498937Sdes	/*
1225147005Sdes	 * get packet type, implies consume.
122698937Sdes	 * return length of payload (without type field)
122798937Sdes	 */
1228147005Sdes	type = buffer_get_char(&incoming_packet);
122998937Sdes	if (type < SSH2_MSG_MIN || type >= SSH2_MSG_LOCAL_MIN)
123098937Sdes		packet_disconnect("Invalid ssh2 packet type: %d", type);
123198937Sdes	if (type == SSH2_MSG_NEWKEYS)
123298937Sdes		set_newkeys(MODE_IN);
123398937Sdes	else if (type == SSH2_MSG_USERAUTH_SUCCESS && !server_side)
123498937Sdes		packet_enable_delayed_compress();
1235147005Sdes#ifdef PACKET_DEBUG
1236147005Sdes	fprintf(stderr, "read/plain[%d]:\r\n", type);
123798937Sdes	buffer_dump(&incoming_packet);
123898937Sdes#endif
123998937Sdes	/* reset for next packet */
124098937Sdes	packet_length = 0;
124198937Sdes	return type;
1242147005Sdes}
124398937Sdes
124498937Sdesint
124598937Sdespacket_read_poll_seqnr(u_int32_t *seqnr_p)
124698937Sdes{
124798937Sdes	u_int reason, seqnr;
124898937Sdes	u_char type;
124998937Sdes	char *msg;
125098937Sdes
125198937Sdes	for (;;) {
1252147005Sdes		if (compat20) {
1253147005Sdes			type = packet_read_poll2(seqnr_p);
1254147005Sdes			if (type) {
1255147005Sdes				keep_alive_timeouts = 0;
125698937Sdes				DBG(debug("received packet type %d", type));
125798937Sdes			}
125898937Sdes			switch (type) {
1259126277Sdes			case SSH2_MSG_IGNORE:
126098937Sdes				debug3("Received SSH2_MSG_IGNORE");
126198937Sdes				break;
126298937Sdes			case SSH2_MSG_DEBUG:
126398937Sdes				packet_get_char();
1264149753Sdes				msg = packet_get_string(NULL);
126598937Sdes				debug("Remote: %.900s", msg);
1266147005Sdes				xfree(msg);
126798937Sdes				msg = packet_get_string(NULL);
126898937Sdes				xfree(msg);
126998937Sdes				break;
1270124211Sdes			case SSH2_MSG_DISCONNECT:
127198937Sdes				reason = packet_get_int();
1272147005Sdes				msg = packet_get_string(NULL);
127398937Sdes				logit("Received disconnect from %s: %u: %.400s",
127498937Sdes				    get_remote_ipaddr(), reason, msg);
127598937Sdes				xfree(msg);
1276147005Sdes				cleanup_exit(255);
127798937Sdes				break;
1278147005Sdes			case SSH2_MSG_UNIMPLEMENTED:
1279126277Sdes				seqnr = packet_get_int();
1280126277Sdes				debug("Received SSH2_MSG_UNIMPLEMENTED for %u",
1281147005Sdes				    seqnr);
1282126277Sdes				break;
128398937Sdes			default:
128498937Sdes				return type;
128598937Sdes			}
128698937Sdes		} else {
128798937Sdes			type = packet_read_poll1();
128898937Sdes			switch (type) {
128998937Sdes			case SSH_MSG_IGNORE:
129098937Sdes				break;
129198937Sdes			case SSH_MSG_DEBUG:
1292147005Sdes				msg = packet_get_string(NULL);
129398937Sdes				debug("Remote: %.900s", msg);
129498937Sdes				xfree(msg);
129598937Sdes				break;
129698937Sdes			case SSH_MSG_DISCONNECT:
129798937Sdes				msg = packet_get_string(NULL);
129898937Sdes				logit("Received disconnect from %s: %.400s",
129998937Sdes				    get_remote_ipaddr(), msg);
130098937Sdes				cleanup_exit(255);
130198937Sdes				break;
1302147005Sdes			default:
130398937Sdes				if (type)
130498937Sdes					DBG(debug("received packet type %d", type));
130598937Sdes				return type;
130698937Sdes			}
130798937Sdes		}
130898937Sdes	}
130998937Sdes}
131098937Sdes
1311147005Sdesint
131298937Sdespacket_read_poll(void)
1313147005Sdes{
131498937Sdes	return packet_read_poll_seqnr(NULL);
1315147005Sdes}
1316147005Sdes
131798937Sdes/*
131898937Sdes * Buffers the given amount of input characters.  This is intended to be used
131998937Sdes * together with packet_read_poll.
132098937Sdes */
132198937Sdes
132298937Sdesvoid
132398937Sdespacket_process_incoming(const char *buf, u_int len)
132498937Sdes{
132598937Sdes	buffer_append(&input, buf, len);
132698937Sdes}
1327204917Sdes
1328204917Sdes/* Returns a character from the packet. */
132998937Sdes
133098937Sdesu_int
1331147005Sdespacket_get_char(void)
133298937Sdes{
1333147005Sdes	char ch;
133498937Sdes
133598937Sdes	buffer_get(&incoming_packet, &ch, 1);
1336147005Sdes	return (u_char) ch;
133798937Sdes}
133898937Sdes
133998937Sdes/* Returns an integer from the packet data. */
134098937Sdes
134198937Sdesu_int
134298937Sdespacket_get_int(void)
134398937Sdes{
134498937Sdes	return buffer_get_int(&incoming_packet);
134598937Sdes}
134698937Sdes
134798937Sdes/*
134898937Sdes * Returns an arbitrary precision integer from the packet data.  The integer
134998937Sdes * must have been initialized before this call.
135098937Sdes */
1351149753Sdes
135298937Sdesvoid
1353147005Sdespacket_get_bignum(BIGNUM * value)
135498937Sdes{
135598937Sdes	buffer_get_bignum(&incoming_packet, value);
1356149753Sdes}
1357106130Sdes
135898937Sdesvoid
1359147005Sdespacket_get_bignum2(BIGNUM * value)
136098937Sdes{
136198937Sdes	buffer_get_bignum2(&incoming_packet, value);
136298937Sdes}
136398937Sdes
136498937Sdesvoid *
136598937Sdespacket_get_raw(u_int *length_ptr)
1366147005Sdes{
136798937Sdes	u_int bytes = buffer_len(&incoming_packet);
136898937Sdes
136998937Sdes	if (length_ptr != NULL)
137098937Sdes		*length_ptr = bytes;
1371149753Sdes	return buffer_ptr(&incoming_packet);
137298937Sdes}
137398937Sdes
1374147005Sdesint
137598937Sdespacket_remaining(void)
1376147005Sdes{
1377149753Sdes	return buffer_len(&incoming_packet);
1378147005Sdes}
1379147005Sdes
1380147005Sdes/*
1381106130Sdes * Returns a string from the packet data.  The string is allocated using
1382147005Sdes * xmalloc; it is the responsibility of the calling program to free it when
138398937Sdes * no longer needed.  The length_ptr argument may be NULL, or point to an
1384147005Sdes * integer into which the length of the string is stored.
138598937Sdes */
138698937Sdes
138798937Sdesvoid *
1388147005Sdespacket_get_string(u_int *length_ptr)
138998937Sdes{
1390147005Sdes	return buffer_get_string(&incoming_packet, length_ptr);
139198937Sdes}
139298937Sdes
139398937Sdesvoid *
139498937Sdespacket_get_string_ptr(u_int *length_ptr)
1395147005Sdes{
1396147005Sdes	return buffer_get_string_ptr(&incoming_packet, length_ptr);
139798937Sdes}
139898937Sdes
139998937Sdes/*
140098937Sdes * Sends a diagnostic message from the server to the client.  This message
1401147005Sdes * can be sent at any time (but not while constructing another message). The
140298937Sdes * message is printed immediately, but only if the client is being executed
140398937Sdes * in verbose mode.  These messages are primarily intended to ease debugging
140498937Sdes * authentication problems.   The length of the formatted message must not
140598937Sdes * exceed 1024 bytes.  This will automatically call packet_write_wait.
140698937Sdes */
140798937Sdes
140898937Sdesvoid
140998937Sdespacket_send_debug(const char *fmt,...)
141098937Sdes{
141198937Sdes	char buf[1024];
141298937Sdes	va_list args;
141398937Sdes
141498937Sdes	if (compat20 && (datafellows & SSH_BUG_DEBUG))
1415147005Sdes		return;
141698937Sdes
141798937Sdes	va_start(args, fmt);
1418113911Sdes	vsnprintf(buf, sizeof(buf), fmt, args);
141998937Sdes	va_end(args);
1420147005Sdes
142198937Sdes	if (compat20) {
142298937Sdes		packet_start(SSH2_MSG_DEBUG);
142398937Sdes		packet_put_char(0);	/* bool: always display */
142498937Sdes		packet_put_cstring(buf);
142598937Sdes		packet_put_cstring("");
142698937Sdes	} else {
1427128460Sdes		packet_start(SSH_MSG_DEBUG);
142898937Sdes		packet_put_cstring(buf);
142998937Sdes	}
143098937Sdes	packet_send();
1431147005Sdes	packet_write_wait();
1432147005Sdes}
143398937Sdes
1434147005Sdes/*
143598937Sdes * Logs the error plus constructs and sends a disconnect packet, closes the
143698937Sdes * connection, and exits.  This function never returns. The error message
143798937Sdes * should not contain a newline.  The length of the formatted message must
143898937Sdes * not exceed 1024 bytes.
143998937Sdes */
144098937Sdes
144198937Sdesvoid
1442147005Sdespacket_disconnect(const char *fmt,...)
144398937Sdes{
144498937Sdes	char buf[1024];
144598937Sdes	va_list args;
144698937Sdes	static int disconnecting = 0;
144798937Sdes
144898937Sdes	if (disconnecting)	/* Guard against recursive invocations. */
144998937Sdes		fatal("packet_disconnect called recursively.");
1450147005Sdes	disconnecting = 1;
145198937Sdes
1452147005Sdes	/*
145398937Sdes	 * Format the message.  Note that the caller must make sure the
1454147005Sdes	 * message is of limited size.
1455147005Sdes	 */
145698937Sdes	va_start(args, fmt);
145798937Sdes	vsnprintf(buf, sizeof(buf), fmt, args);
145898937Sdes	va_end(args);
145998937Sdes
146098937Sdes	/* Display the error locally */
146198937Sdes	logit("Disconnecting: %.100s", buf);
146298937Sdes
146398937Sdes	/* Send the disconnect message to the other side, and wait for it to get sent. */
146498937Sdes	if (compat20) {
146598937Sdes		packet_start(SSH2_MSG_DISCONNECT);
146698937Sdes		packet_put_int(SSH2_DISCONNECT_PROTOCOL_ERROR);
146798937Sdes		packet_put_cstring(buf);
1468192595Sdes		packet_put_cstring("");
1469192595Sdes	} else {
147098937Sdes		packet_start(SSH_MSG_DISCONNECT);
1471192595Sdes		packet_put_cstring(buf);
147298937Sdes	}
1473192595Sdes	packet_send();
1474192595Sdes	packet_write_wait();
147598937Sdes
147698937Sdes	/* Stop listening for connections. */
147798937Sdes	channel_close_all();
1478147005Sdes
1479147005Sdes	/* Close the connection. */
1480147005Sdes	packet_close();
148198937Sdes	cleanup_exit(255);
1482192595Sdes}
1483147005Sdes
1484147005Sdes/* Checks if there is any buffered output, and tries to write some of the output. */
1485192595Sdes
1486192595Sdesvoid
1487192595Sdespacket_write_poll(void)
1488147005Sdes{
1489147005Sdes	int len = buffer_len(&output);
1490147005Sdes
149198937Sdes	if (len > 0) {
149298937Sdes		len = write(connection_out, buffer_ptr(&output), len);
1493124211Sdes		if (len == -1) {
1494147005Sdes			if (errno == EINTR || errno == EAGAIN ||
1495147005Sdes			    errno == EWOULDBLOCK)
149698937Sdes				return;
1497147005Sdes			fatal("Write failed: %.100s", strerror(errno));
149898937Sdes		}
149998937Sdes		if (len == 0)
1500192595Sdes			fatal("Write connection closed");
150198937Sdes		buffer_consume(&output, len);
1502221420Sdes	}
150398937Sdes}
1504147005Sdes
1505147005Sdes
1506147005Sdes/*
1507221420Sdes * Calls packet_write_poll repeatedly until all pending output data has been
1508147005Sdes * written.
150998937Sdes */
151098937Sdes
151198937Sdesvoid
1512147005Sdespacket_write_wait(void)
151398937Sdes{
1514192595Sdes	fd_set *setp;
151598937Sdes	int ret, ms_remain;
1516192595Sdes	struct timeval start, timeout, *timeoutp = NULL;
1517192595Sdes
1518192595Sdes	setp = (fd_set *)xcalloc(howmany(connection_out + 1, NFDBITS),
151998937Sdes	    sizeof(fd_mask));
1520192595Sdes	packet_write_poll();
1521192595Sdes	while (packet_have_data_to_write()) {
1522192595Sdes		memset(setp, 0, howmany(connection_out + 1, NFDBITS) *
1523192595Sdes		    sizeof(fd_mask));
1524192595Sdes		FD_SET(connection_out, setp);
1525192595Sdes
152698937Sdes		if (packet_timeout_ms > 0) {
152798937Sdes			ms_remain = packet_timeout_ms;
1528192595Sdes			timeoutp = &timeout;
152998937Sdes		}
153098937Sdes		for (;;) {
153198937Sdes			if (packet_timeout_ms != -1) {
1532192595Sdes				ms_to_timeval(&timeout, ms_remain);
1533192595Sdes				gettimeofday(&start, NULL);
1534192595Sdes			}
153598937Sdes			if ((ret = select(connection_out + 1, NULL, setp,
153698937Sdes			    NULL, timeoutp)) >= 0)
1537192595Sdes				break;
1538192595Sdes		   	if (errno != EAGAIN && errno != EINTR &&
1539192595Sdes			    errno != EWOULDBLOCK)
1540192595Sdes				break;
1541192595Sdes			if (packet_timeout_ms == -1)
1542192595Sdes				continue;
1543192595Sdes			ms_subtract_diff(&start, &ms_remain);
1544192595Sdes			if (ms_remain <= 0) {
1545192595Sdes				ret = 0;
1546192595Sdes				break;
1547192595Sdes			}
1548192595Sdes		}
1549192595Sdes		if (ret == 0) {
1550192595Sdes			logit("Connection to %.200s timed out while "
1551192595Sdes			    "waiting to write", get_remote_ipaddr());
1552192595Sdes			cleanup_exit(255);
1553192595Sdes		}
1554192595Sdes		packet_write_poll();
1555192595Sdes	}
1556192595Sdes	xfree(setp);
155798937Sdes}
1558147005Sdes
1559147005Sdes/* Returns true if there is buffered data to write to the connection. */
156098937Sdes
156198937Sdesint
1562192595Sdespacket_have_data_to_write(void)
156398937Sdes{
1564192595Sdes	return buffer_len(&output) != 0;
1565192595Sdes}
1566192595Sdes
156798937Sdes/* Returns true if there is not too much data to write to the connection. */
1568192595Sdes
1569192595Sdesint
1570192595Sdespacket_not_very_much_data_to_write(void)
1571192595Sdes{
1572192595Sdes	if (interactive_mode)
1573192595Sdes		return buffer_len(&output) < 16384;
1574192595Sdes	else
1575192595Sdes		return buffer_len(&output) < 128 * 1024;
1576192595Sdes}
1577192595Sdes
1578192595Sdes
1579192595Sdesstatic void
158098937Sdespacket_set_tos(int interactive)
1581192595Sdes{
158298937Sdes#if defined(IP_TOS) && !defined(IP_TOS_IS_BROKEN)
158398937Sdes	int tos = interactive ? IPTOS_LOWDELAY : IPTOS_THROUGHPUT;
158498937Sdes
158598937Sdes	if (!packet_connection_is_on_socket() ||
1586113911Sdes	    !packet_connection_is_ipv4())
158798937Sdes		return;
158898937Sdes	if (setsockopt(connection_in, IPPROTO_IP, IP_TOS, &tos,
1589113911Sdes	    sizeof(tos)) < 0)
159098937Sdes		error("setsockopt IP_TOS %d: %.100s:",
1591113911Sdes		    tos, strerror(errno));
1592113911Sdes#endif
1593113911Sdes}
1594113911Sdes
1595113911Sdes/* Informs that the current session is interactive.  Sets IP flags for that. */
1596113911Sdes
1597113911Sdesvoid
1598113911Sdespacket_set_interactive(int interactive)
1599192595Sdes{
1600192595Sdes	static int called = 0;
1601192595Sdes
1602192595Sdes	if (called)
1603113911Sdes		return;
1604113911Sdes	called = 1;
1605126277Sdes
160698937Sdes	/* Record that we are in interactive mode. */
1607113911Sdes	interactive_mode = interactive;
1608113911Sdes
1609113911Sdes	/* Only set socket options if using a socket.  */
1610157019Sdes	if (!packet_connection_is_on_socket())
1611113911Sdes		return;
161298937Sdes	set_nodelay(connection_in);
161398937Sdes	packet_set_tos(interactive);
1614113911Sdes}
1615113911Sdes
161698937Sdes/* Returns true if the current connection is interactive. */
1617192595Sdes
161898937Sdesint
1619147005Sdespacket_is_interactive(void)
1620207319Sdes{
1621207319Sdes	return interactive_mode;
1622202213Sed}
1623202213Sed
1624202213Sedint
1625202213Sedpacket_set_maxsize(u_int s)
1626202213Sed{
1627202213Sed	static int called = 0;
1628202213Sed
1629202213Sed	if (called) {
1630202213Sed		logit("packet_set_maxsize: called twice: old %d new %d",
1631202213Sed		    max_packet_size, s);
1632202213Sed		return -1;
1633202213Sed	}
1634202213Sed	if (s < 4 * 1024 || s > 1024 * 1024) {
1635202213Sed		logit("packet_set_maxsize: bad size %d", s);
1636202213Sed		return -1;
1637202213Sed	}
1638202213Sed	called = 1;
1639202213Sed	debug("packet_set_maxsize: setting to %d", s);
1640202213Sed	max_packet_size = s;
1641202213Sed	return s;
1642202213Sed}
1643202213Sed
1644207319Sdes/* roundup current message to pad bytes */
1645202213Sedvoid
1646147005Sdespacket_add_padding(u_char pad)
1647147005Sdes{
1648147005Sdes	extra_pad = pad;
1649147005Sdes}
1650147005Sdes
1651147005Sdes/*
1652147005Sdes * 9.2.  Ignored Data Message
1653147005Sdes *
1654147005Sdes *   byte      SSH_MSG_IGNORE
1655147005Sdes *   string    data
1656147005Sdes *
1657147005Sdes * All implementations MUST understand (and ignore) this message at any
1658147005Sdes * time (after receiving the protocol version). No implementation is
1659147005Sdes * required to send them. This message can be used as an additional
1660147005Sdes * protection measure against advanced traffic analysis techniques.
1661157019Sdes */
1662147005Sdesvoid
1663147005Sdespacket_send_ignore(int nbytes)
1664147005Sdes{
1665147005Sdes	u_int32_t rnd = 0;
1666147005Sdes	int i;
1667147005Sdes
1668147005Sdes	packet_start(compat20 ? SSH2_MSG_IGNORE : SSH_MSG_IGNORE);
1669147005Sdes	packet_put_int(nbytes);
1670147005Sdes	for (i = 0; i < nbytes; i++) {
1671147005Sdes		if (i % 4 == 0)
1672147005Sdes			rnd = arc4random();
1673147005Sdes		packet_put_char((u_char)rnd & 0xff);
1674147005Sdes		rnd >>= 8;
1675147005Sdes	}
1676147005Sdes}
1677147005Sdes
1678147005Sdes#define MAX_PACKETS	(1U<<31)
1679221420Sdesint
1680147005Sdespacket_need_rekeying(void)
1681147005Sdes{
1682147005Sdes	if (datafellows & SSH_BUG_NOREKEY)
1683147005Sdes		return 0;
1684147005Sdes	return
1685147005Sdes	    (p_send.packets > MAX_PACKETS) ||
1686147005Sdes	    (p_read.packets > MAX_PACKETS) ||
1687147005Sdes	    (max_blocks_out && (p_send.blocks > max_blocks_out)) ||
1688147005Sdes	    (max_blocks_in  && (p_read.blocks > max_blocks_in));
1689147005Sdes}
1690147005Sdes
1691147005Sdesvoid
1692147005Sdespacket_set_rekey_limit(u_int32_t bytes)
1693147005Sdes{
1694147005Sdes	rekey_limit = bytes;
1695147005Sdes}
1696147005Sdes
1697147005Sdesvoid
1698147005Sdespacket_set_server(void)
1699147005Sdes{
1700147005Sdes	server_side = 1;
1701147005Sdes}
1702147005Sdes
1703147005Sdesvoid
1704147005Sdespacket_set_authenticated(void)
1705147005Sdes{
1706147005Sdes	after_authentication = 1;
1707147005Sdes}
1708147005Sdes