packet.c revision 99060
1248619Sdes/*
2224638Sbrooks * Author: Tatu Ylonen <ylo@cs.hut.fi>
357429Smarkm * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
457429Smarkm *                    All rights reserved
557429Smarkm * This file contains code implementing the packet protocol and communication
657429Smarkm * with the other side.  This same code is used both on client and server side.
757429Smarkm *
857429Smarkm * As far as I am concerned, the code I have written for this software
960573Skris * can be used freely for any purpose.  Any derived versions of this
1065668Skris * software must be clearly marked as such, and if the derived work is
1165668Skris * incompatible with the protocol description in the RFC file, it must be
1265668Skris * called by a name other than "ssh" or "Secure Shell".
1365668Skris *
1465668Skris *
1565668Skris * SSH2 packet format added by Markus Friedl.
1665668Skris * Copyright (c) 2000, 2001 Markus Friedl.  All rights reserved.
1760573Skris *
1892555Sdes * Redistribution and use in source and binary forms, with or without
1960573Skris * modification, are permitted provided that the following conditions
2065668Skris * are met:
2165668Skris * 1. Redistributions of source code must retain the above copyright
2265668Skris *    notice, this list of conditions and the following disclaimer.
2365668Skris * 2. Redistributions in binary form must reproduce the above copyright
2465668Skris *    notice, this list of conditions and the following disclaimer in the
2565668Skris *    documentation and/or other materials provided with the distribution.
2665668Skris *
2765668Skris * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
2865668Skris * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
2965668Skris * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
3065668Skris * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
3165668Skris * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
3265668Skris * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
3365668Skris * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
3465668Skris * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
3565668Skris * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
3665668Skris * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3765668Skris */
3865668Skris
3957429Smarkm#include "includes.h"
4057429SmarkmRCSID("$OpenBSD: packet.c,v 1.96 2002/06/23 21:10:02 deraadt Exp $");
4157429Smarkm
42162852Sdes#include "xmalloc.h"
43162852Sdes#include "buffer.h"
44124208Sdes#include "packet.h"
45162852Sdes#include "bufaux.h"
46162852Sdes#include "crc32.h"
47162852Sdes#include "getput.h"
48162852Sdes
49162852Sdes#include "compress.h"
50124208Sdes#include "deattack.h"
51162852Sdes#include "channels.h"
52162852Sdes
53162852Sdes#include "compat.h"
54162852Sdes#include "ssh1.h"
55162852Sdes#include "ssh2.h"
56162852Sdes
57162852Sdes#include "cipher.h"
58162852Sdes#include "kex.h"
59162852Sdes#include "mac.h"
60162852Sdes#include "log.h"
61162852Sdes#include "canohost.h"
62162852Sdes#include "misc.h"
6357429Smarkm#include "ssh.h"
6457429Smarkm
6557429Smarkm#ifdef PACKET_DEBUG
6657429Smarkm#define DBG(x) x
6757429Smarkm#else
6857429Smarkm#define DBG(x)
6960573Skris#endif
7060573Skris
7176259Sgreen/*
7260573Skris * This variable contains the file descriptors used for communicating with
7369587Sgreen * the other side.  connection_in is used for reading; connection_out for
74162852Sdes * writing.  These can be the same descriptor, in which case it is assumed to
7560573Skris * be a socket.
7676259Sgreen */
7776259Sgreenstatic int connection_in = -1;
7876259Sgreenstatic int connection_out = -1;
7992555Sdes
8098675Sdes/* Protocol flags for the remote side. */
81197679Sdesstatic u_int remote_protocol_flags = 0;
8260573Skris
8360573Skris/* Encryption context for receiving data.  This is only used for decryption. */
8460573Skrisstatic CipherContext receive_context;
8560573Skris
8660573Skris/* Encryption context for sending data.  This is only used for encryption. */
8760573Skrisstatic CipherContext send_context;
8860573Skris
89192595Sdes/* Buffer for raw input data from the socket. */
90192595SdesBuffer input;
91197679Sdes
92197679Sdes/* Buffer for raw output data going to the socket. */
93197679SdesBuffer output;
94197679Sdes
95197679Sdes/* Buffer for the partial outgoing packet being constructed. */
96197679Sdesstatic Buffer outgoing_packet;
9757429Smarkm
98197679Sdes/* Buffer for the incoming packet currently being processed. */
99197679Sdesstatic Buffer incoming_packet;
100197679Sdes
101197679Sdes/* Scratch buffer for packet compression/decompression. */
102197679Sdesstatic Buffer compression_buffer;
10357429Smarkmstatic int compression_buffer_ready = 0;
104197679Sdes
105197679Sdes/* Flag indicating whether packet compression/decompression is enabled. */
106197679Sdesstatic int packet_compression = 0;
107197679Sdes
108197679Sdes/* default maximum packet size */
109197679Sdesint max_packet_size = 32768;
110197679Sdes
111197679Sdes/* Flag indicating whether this module has been initialized. */
112197679Sdesstatic int initialized = 0;
11357429Smarkm
114197679Sdes/* Set to true if the connection is interactive. */
115197679Sdesstatic int interactive_mode = 0;
11657429Smarkm
117197679Sdes/* Session key information for Encryption and MAC */
118197679SdesNewkeys *newkeys[MODE_MAX];
11957429Smarkmstatic u_int32_t read_seqnr = 0;
120197679Sdesstatic u_int32_t send_seqnr = 0;
121197679Sdes
12257429Smarkm/* Session key for protocol v1 */
123197679Sdesstatic u_char ssh1_key[SSH_SESSION_KEY_LENGTH];
124197679Sdesstatic u_int ssh1_keylen;
12557429Smarkm
126197679Sdes/* roundup current message to extra_pad bytes */
127197679Sdesstatic u_char extra_pad = 0;
12857429Smarkm
129197679Sdes/*
130197679Sdes * Sets the descriptors used for communication.  Disables encryption until
13157429Smarkm * packet_set_encryption_key is called.
132197679Sdes */
133197679Sdesvoid
13457429Smarkmpacket_set_connection(int fd_in, int fd_out)
135197679Sdes{
136197679Sdes	Cipher *none = cipher_by_name("none");
137197679Sdes	if (none == NULL)
13857429Smarkm		fatal("packet_set_connection: cannot load cipher 'none'");
139197679Sdes	connection_in = fd_in;
140197679Sdes	connection_out = fd_out;
141197679Sdes	cipher_init(&send_context, none, "", 0, NULL, 0, CIPHER_ENCRYPT);
142197679Sdes	cipher_init(&receive_context, none, "", 0, NULL, 0, CIPHER_DECRYPT);
143197679Sdes	newkeys[MODE_IN] = newkeys[MODE_OUT] = NULL;
14457429Smarkm	if (!initialized) {
145197679Sdes		initialized = 1;
146197679Sdes		buffer_init(&input);
14757429Smarkm		buffer_init(&output);
148197679Sdes		buffer_init(&outgoing_packet);
149197679Sdes		buffer_init(&incoming_packet);
150149749Sdes	}
151197679Sdes	/* Kludge: arrange the close function to be called from fatal(). */
152197679Sdes	fatal_add_cleanup((void (*) (void *)) packet_close, NULL);
153149749Sdes}
154197679Sdes
155197679Sdes/* Returns 1 if remote host is connected via socket, 0 if not. */
156181111Sdes
157197679Sdesint
158197679Sdespacket_connection_is_on_socket(void)
159181111Sdes{
160197679Sdes	struct sockaddr_storage from, to;
16160573Skris	socklen_t fromlen, tolen;
162197679Sdes
163197679Sdes	/* filedescriptors in and out are the same, so it's a socket */
164124208Sdes	if (connection_in == connection_out)
165197679Sdes		return 1;
166197679Sdes	fromlen = sizeof(from);
167197679Sdes	memset(&from, 0, sizeof(from));
16898675Sdes	if (getpeername(connection_in, (struct sockaddr *)&from, &fromlen) < 0)
169197679Sdes		return 0;
170197679Sdes	tolen = sizeof(to);
17160573Skris	memset(&to, 0, sizeof(to));
172197679Sdes	if (getpeername(connection_out, (struct sockaddr *)&to, &tolen) < 0)
173197679Sdes		return 0;
174197679Sdes	if (fromlen != tolen || memcmp(&from, &to, fromlen) != 0)
175192595Sdes		return 0;
176197679Sdes	if (from.ss_family != AF_INET && from.ss_family != AF_INET6)
177197679Sdes		return 0;
178197679Sdes	return 1;
179197679Sdes}
180197679Sdes
181197679Sdes/*
182197679Sdes * Exports an IV from the CipherContext required to export the key
183197679Sdes * state back from the unprivileged child to the privileged parent
184197679Sdes * process.
185197679Sdes */
186197679Sdes
187197679Sdesvoid
188197679Sdespacket_get_keyiv(int mode, u_char *iv, u_int len)
189197679Sdes{
190197679Sdes	CipherContext *cc;
191197679Sdes
192197679Sdes	if (mode == MODE_OUT)
193197679Sdes		cc = &send_context;
194197679Sdes	else
195197679Sdes		cc = &receive_context;
196124208Sdes
197124208Sdes	cipher_get_keyiv(cc, iv, len);
198197679Sdes}
199224638Sbrooks
200224638Sbrooksint
201224638Sbrookspacket_get_keycontext(int mode, u_char *dat)
202197679Sdes{
203197679Sdes	CipherContext *cc;
204197679Sdes
205197679Sdes	if (mode == MODE_OUT)
206221420Sdes		cc = &send_context;
207197679Sdes	else
208221420Sdes		cc = &receive_context;
209221420Sdes
210221420Sdes	return (cipher_get_keycontext(cc, dat));
211221420Sdes}
212221420Sdes
213197679Sdesvoid
214197679Sdespacket_set_keycontext(int mode, u_char *dat)
21557429Smarkm{
21657429Smarkm	CipherContext *cc;
21757429Smarkm
21857429Smarkm	if (mode == MODE_OUT)
21957429Smarkm		cc = &send_context;
22057429Smarkm	else
22157429Smarkm		cc = &receive_context;
22269587Sgreen
223106121Sdes	cipher_set_keycontext(cc, dat);
22469587Sgreen}
22569587Sgreen
226197679Sdesint
227197679Sdespacket_get_keyiv_len(int mode)
228197679Sdes{
229197679Sdes	CipherContext *cc;
230197679Sdes
231137015Sdes	if (mode == MODE_OUT)
232197679Sdes		cc = &send_context;
233137015Sdes	else
234197679Sdes		cc = &receive_context;
235197679Sdes
236197679Sdes	return (cipher_get_keyiv_len(cc));
237197679Sdes}
238197679Sdesvoid
239197679Sdespacket_set_iv(int mode, u_char *dat)
240197679Sdes{
241197679Sdes	CipherContext *cc;
242197679Sdes
24357429Smarkm	if (mode == MODE_OUT)
24457429Smarkm		cc = &send_context;
24557429Smarkm	else
246181111Sdes		cc = &receive_context;
247181111Sdes
248181111Sdes	cipher_set_keyiv(cc, dat);
249240075Sdes}
250197679Sdesint
251181111Sdespacket_get_ssh1_cipher()
252181111Sdes{
253181111Sdes	return (cipher_get_number(receive_context.cipher));
254197679Sdes}
255181111Sdes
256197679Sdes
257181111Sdesu_int32_t
258181111Sdespacket_get_seqnr(int mode)
259192595Sdes{
260192595Sdes	return (mode == MODE_IN ? read_seqnr : send_seqnr);
261192595Sdes}
262197679Sdes
263192595Sdesvoid
264192595Sdespacket_set_seqnr(int mode, u_int32_t seqnr)
265192595Sdes{
266197679Sdes	if (mode == MODE_IN)
267197679Sdes		read_seqnr = seqnr;
268197679Sdes	else if (mode == MODE_OUT)
269197679Sdes		send_seqnr = seqnr;
270197679Sdes	else
271197679Sdes		fatal("packet_set_seqnr: bad mode %d", mode);
272197679Sdes}
273192595Sdes
274192595Sdes/* returns 1 if connection is via ipv4 */
275192595Sdes
276192595Sdesint
277192595Sdespacket_connection_is_ipv4(void)
278192595Sdes{
279192595Sdes	struct sockaddr_storage to;
280192595Sdes	socklen_t tolen = sizeof(to);
281192595Sdes
282248619Sdes	memset(&to, 0, sizeof(to));
283192595Sdes	if (getsockname(connection_out, (struct sockaddr *)&to, &tolen) < 0)
284192595Sdes		return 0;
285197679Sdes	if (to.ss_family == AF_INET)
286197679Sdes		return 1;
287192595Sdes#ifdef IPV4_IN_IPV6
288197679Sdes	if (to.ss_family == AF_INET6 &&
289197679Sdes	    IN6_IS_ADDR_V4MAPPED(&((struct sockaddr_in6 *)&to)->sin6_addr))
290192595Sdes		return 1;
291192595Sdes#endif
29257429Smarkm	return 0;
29357429Smarkm}
29457429Smarkm
29592555Sdes/* Sets the connection into non-blocking mode. */
29657429Smarkm
29757429Smarkmvoid
29857429Smarkmpacket_set_nonblocking(void)
29957429Smarkm{
30057429Smarkm	/* Set the socket into non-blocking mode. */
301197679Sdes	if (fcntl(connection_in, F_SETFL, O_NONBLOCK) < 0)
30257429Smarkm		error("fcntl O_NONBLOCK: %.100s", strerror(errno));
30357429Smarkm
30457429Smarkm	if (connection_out != connection_in) {
305197679Sdes		if (fcntl(connection_out, F_SETFL, O_NONBLOCK) < 0)
306197679Sdes			error("fcntl O_NONBLOCK: %.100s", strerror(errno));
30757429Smarkm	}
30857429Smarkm}
30957429Smarkm
310197679Sdes/* Returns the socket used for reading. */
311197679Sdes
31257429Smarkmint
31357429Smarkmpacket_get_connection_in(void)
31457429Smarkm{
31557429Smarkm	return connection_in;
31657429Smarkm}
31757429Smarkm
31857429Smarkm/* Returns the descriptor used for writing. */
31957429Smarkm
32098675Sdesint
32198675Sdespacket_get_connection_out(void)
32298675Sdes{
32398675Sdes	return connection_out;
32498675Sdes}
32598675Sdes
32698675Sdes/* Closes the connection and clears and frees internal data structures. */
32798675Sdes
32898675Sdesvoid
32998675Sdespacket_close(void)
33098675Sdes{
33198675Sdes	if (!initialized)
332197679Sdes		return;
33398675Sdes	initialized = 0;
334197679Sdes	if (connection_in == connection_out) {
33598675Sdes		shutdown(connection_out, SHUT_RDWR);
33698675Sdes		close(connection_out);
33798675Sdes	} else {
33898675Sdes		close(connection_in);
33998675Sdes		close(connection_out);
34098675Sdes	}
34198675Sdes	buffer_free(&input);
34298675Sdes	buffer_free(&output);
34398675Sdes	buffer_free(&outgoing_packet);
34498675Sdes	buffer_free(&incoming_packet);
345197679Sdes	if (compression_buffer_ready) {
34698675Sdes		buffer_free(&compression_buffer);
347197679Sdes		buffer_compress_uninit();
34898675Sdes	}
34998675Sdes	cipher_cleanup(&send_context);
35098675Sdes	cipher_cleanup(&receive_context);
35198675Sdes}
35298675Sdes
35398675Sdes/* Sets remote side protocol flags. */
35498675Sdes
35598675Sdesvoid
35698675Sdespacket_set_protocol_flags(u_int protocol_flags)
35798675Sdes{
358197679Sdes	remote_protocol_flags = protocol_flags;
35998675Sdes}
360197679Sdes
36198675Sdes/* Returns the remote protocol flags set earlier by the above function. */
36298675Sdes
36398675Sdesu_int
36498675Sdespacket_get_protocol_flags(void)
36598675Sdes{
36698675Sdes	return remote_protocol_flags;
36798675Sdes}
36898675Sdes
36998675Sdes/*
37098675Sdes * Starts packet compression from the next packet on in both directions.
371197679Sdes * Level is compression level 1 (fastest) - 9 (slow, best) as in gzip.
37298675Sdes */
373197679Sdes
37498675Sdesstatic void
37598675Sdespacket_init_compression(void)
37698675Sdes{
377162852Sdes	if (compression_buffer_ready == 1)
37898675Sdes		return;
37998675Sdes	compression_buffer_ready = 1;
38098675Sdes	buffer_init(&compression_buffer);
38198675Sdes}
38298675Sdes
38398675Sdesvoid
384197679Sdespacket_start_compression(int level)
38598675Sdes{
386197679Sdes	if (packet_compression && !compat20)
38798675Sdes		fatal("Compression already enabled.");
38898675Sdes	packet_compression = 1;
38998675Sdes	packet_init_compression();
390162852Sdes	buffer_compress_init_send(level);
39198675Sdes	buffer_compress_init_recv();
392124208Sdes}
39398675Sdes
394197679Sdes/*
39598675Sdes * Causes any further packets to be encrypted using the given key.  The same
39698675Sdes * key is used for both sending and reception.  However, both directions are
397124208Sdes * encrypted independently of each other.
398221420Sdes */
399221420Sdes
400124208Sdesvoid
401124208Sdespacket_set_encryption_key(const u_char *key, u_int keylen,
40298675Sdes    int number)
403197679Sdes{
404197679Sdes	Cipher *cipher = cipher_by_number(number);
405181111Sdes	if (cipher == NULL)
406181111Sdes		fatal("packet_set_encryption_key: unknown cipher number %d", number);
407181111Sdes	if (keylen < 20)
408181111Sdes		fatal("packet_set_encryption_key: keylen too small: %d", keylen);
409181111Sdes	if (keylen > SSH_SESSION_KEY_LENGTH)
410181111Sdes		fatal("packet_set_encryption_key: keylen too big: %d", keylen);
411181111Sdes	memcpy(ssh1_key, key, keylen);
412181111Sdes	ssh1_keylen = keylen;
41398675Sdes	cipher_init(&send_context, cipher, key, keylen, NULL, 0, CIPHER_ENCRYPT);
41498675Sdes	cipher_init(&receive_context, cipher, key, keylen, NULL, 0, CIPHER_DECRYPT);
41598675Sdes}
416181111Sdes
417181111Sdesu_int
41898675Sdespacket_get_encryption_key(u_char *key)
419124208Sdes{
420124208Sdes	if (key == NULL)
421197679Sdes		return (ssh1_keylen);
422197679Sdes	memcpy(key, ssh1_key, ssh1_keylen);
423124208Sdes	return (ssh1_keylen);
424124208Sdes}
425124208Sdes
426181111Sdes/* Start constructing a packet to send. */
42798675Sdesvoid
42898675Sdespacket_start(u_char type)
429226046Sdes{
430226046Sdes	u_char buf[9];
43157429Smarkm	int len;
43257429Smarkm
43357429Smarkm	DBG(debug("packet_start[%d]", type));
43457429Smarkm	len = compat20 ? 6 : 9;
43557429Smarkm	memset(buf, 0, len - 1);
436197679Sdes	buf[len - 1] = type;
437197679Sdes	buffer_clear(&outgoing_packet);
43857429Smarkm	buffer_append(&outgoing_packet, buf, len);
43998937Sdes}
440126274Sdes
44198937Sdes/* Append payload. */
442226046Sdesvoid
44398937Sdespacket_put_char(int value)
444226046Sdes{
44557429Smarkm	char ch = value;
44657429Smarkm	buffer_append(&outgoing_packet, &ch, 1);
44757429Smarkm}
44857429Smarkmvoid
44957429Smarkmpacket_put_int(u_int value)
45092555Sdes{
45157429Smarkm	buffer_put_int(&outgoing_packet, value);
45257429Smarkm}
453197679Sdesvoid
45457429Smarkmpacket_put_string(const void *buf, u_int len)
455197679Sdes{
456197679Sdes	buffer_put_string(&outgoing_packet, buf, len);
45757429Smarkm}
45857429Smarkmvoid
45957429Smarkmpacket_put_cstring(const char *str)
46057429Smarkm{
46157429Smarkm	buffer_put_cstring(&outgoing_packet, str);
46292555Sdes}
46357429Smarkmvoid
464197679Sdespacket_put_raw(const void *buf, u_int len)
46557429Smarkm{
46657429Smarkm	buffer_append(&outgoing_packet, buf, len);
46757429Smarkm}
46857429Smarkmvoid
46957429Smarkmpacket_put_bignum(BIGNUM * value)
47092555Sdes{
47157429Smarkm	buffer_put_bignum(&outgoing_packet, value);
472197679Sdes}
47357429Smarkmvoid
47457429Smarkmpacket_put_bignum2(BIGNUM * value)
47557429Smarkm{
47657429Smarkm	buffer_put_bignum2(&outgoing_packet, value);
47757429Smarkm}
47892555Sdes
47957429Smarkm/*
480197679Sdes * Finalizes and sends the packet.  If the encryption key has been set,
48157429Smarkm * encrypts the packet before sending.
482197679Sdes */
483197679Sdes
484197679Sdesstatic void
485197679Sdespacket_send1(void)
48657429Smarkm{
487197679Sdes	u_char buf[8], *cp;
488197679Sdes	int i, padding, len;
48957429Smarkm	u_int checksum;
490197679Sdes	u_int32_t rand = 0;
491197679Sdes
492197679Sdes	/*
493197679Sdes	 * If using packet compression, compress the payload of the outgoing
494197679Sdes	 * packet.
495197679Sdes	 */
49657429Smarkm	if (packet_compression) {
49757429Smarkm		buffer_clear(&compression_buffer);
498197679Sdes		/* Skip padding. */
499197679Sdes		buffer_consume(&outgoing_packet, 8);
50057429Smarkm		/* padding */
50157429Smarkm		buffer_append(&compression_buffer, "\0\0\0\0\0\0\0\0", 8);
50257429Smarkm		buffer_compress(&outgoing_packet, &compression_buffer);
50357429Smarkm		buffer_clear(&outgoing_packet);
50457429Smarkm		buffer_append(&outgoing_packet, buffer_ptr(&compression_buffer),
50576259Sgreen		    buffer_len(&compression_buffer));
50657429Smarkm	}
507197679Sdes	/* Compute packet length without padding (add checksum, remove padding). */
50857429Smarkm	len = buffer_len(&outgoing_packet) + 4 - 8;
50957429Smarkm
51057429Smarkm	/* Insert padding. Initialized to zero in packet_start1() */
51157429Smarkm	padding = 8 - len % 8;
51276259Sgreen	if (!send_context.plaintext) {
51392555Sdes		cp = buffer_ptr(&outgoing_packet);
51457429Smarkm		for (i = 0; i < padding; i++) {
515197679Sdes			if (i % 4 == 0)
51657429Smarkm				rand = arc4random();
51757429Smarkm			cp[7 - i] = rand & 0xff;
51857429Smarkm			rand >>= 8;
51957429Smarkm		}
52057429Smarkm	}
52157429Smarkm	buffer_consume(&outgoing_packet, 8 - padding);
52257429Smarkm
52392555Sdes	/* Add check bytes. */
52492555Sdes	checksum = ssh_crc32(buffer_ptr(&outgoing_packet),
52576259Sgreen	    buffer_len(&outgoing_packet));
526197679Sdes	PUT_32BIT(buf, checksum);
52776259Sgreen	buffer_append(&outgoing_packet, buf, 4);
528197679Sdes
529197679Sdes#ifdef PACKET_DEBUG
53076259Sgreen	fprintf(stderr, "packet_send plain: ");
53176259Sgreen	buffer_dump(&outgoing_packet);
53276259Sgreen#endif
53357429Smarkm
53457429Smarkm	/* Append to output. */
535197679Sdes	PUT_32BIT(buf, len);
53657429Smarkm	buffer_append(&output, buf, 4);
537197679Sdes	cp = buffer_append_space(&output, buffer_len(&outgoing_packet));
53876259Sgreen	cipher_crypt(&send_context, cp, buffer_ptr(&outgoing_packet),
53976259Sgreen	    buffer_len(&outgoing_packet));
54076259Sgreen
54157429Smarkm#ifdef PACKET_DEBUG
54257429Smarkm	fprintf(stderr, "encrypted: ");
54357429Smarkm	buffer_dump(&output);
54457429Smarkm#endif
54557429Smarkm
54657429Smarkm	buffer_clear(&outgoing_packet);
54757429Smarkm
54898675Sdes	/*
54957429Smarkm	 * Note that the packet is now only buffered in output.  It won\'t be
550221420Sdes	 * actually sent until packet_write_wait or packet_write_poll is
55157429Smarkm	 * called.
55269587Sgreen	 */
553106121Sdes}
55469587Sgreen
55569587Sgreenvoid
55660573Skrisset_newkeys(int mode)
55769587Sgreen{
55898675Sdes	Enc *enc;
55998675Sdes	Mac *mac;
560197679Sdes	Comp *comp;
561197679Sdes	CipherContext *cc;
562197679Sdes	int encrypt;
563197679Sdes
564197679Sdes	debug("newkeys: mode %d", mode);
565197679Sdes
56657429Smarkm	if (mode == MODE_OUT) {
56757429Smarkm		cc = &send_context;
56898675Sdes		encrypt = CIPHER_ENCRYPT;
56998675Sdes	} else {
57098675Sdes		cc = &receive_context;
57198675Sdes		encrypt = CIPHER_DECRYPT;
572197679Sdes	}
573197679Sdes	if (newkeys[mode] != NULL) {
574197679Sdes		debug("newkeys: rekeying");
57598675Sdes		cipher_cleanup(cc);
57698675Sdes		enc  = &newkeys[mode]->enc;
57792555Sdes		mac  = &newkeys[mode]->mac;
57857429Smarkm		comp = &newkeys[mode]->comp;
57992555Sdes		memset(mac->key, 0, mac->key_len);
58057429Smarkm		xfree(enc->name);
58192555Sdes		xfree(enc->iv);
58292555Sdes		xfree(enc->key);
58357429Smarkm		xfree(mac->name);
58492555Sdes		xfree(mac->key);
58592555Sdes		xfree(comp->name);
58692555Sdes		xfree(newkeys[mode]);
58792555Sdes	}
588197679Sdes	newkeys[mode] = kex_get_newkeys(mode);
589197679Sdes	if (newkeys[mode] == NULL)
59057429Smarkm		fatal("newkeys: no keys for mode %d", mode);
59157429Smarkm	enc  = &newkeys[mode]->enc;
59292555Sdes	mac  = &newkeys[mode]->mac;
59360573Skris	comp = &newkeys[mode]->comp;
59457429Smarkm	if (mac->md != NULL)
59557429Smarkm		mac->enabled = 1;
59657429Smarkm	DBG(debug("cipher_init_context: %d", mode));
597106121Sdes	cipher_init(cc, enc->cipher, enc->key, enc->key_len,
598197679Sdes	    enc->iv, enc->block_size, encrypt);
59957429Smarkm	/* Deleting the keys does not gain extra security */
600162852Sdes	/* memset(enc->iv,  0, enc->block_size);
60157429Smarkm	   memset(enc->key, 0, enc->key_len); */
60276259Sgreen	if (comp->type != 0 && comp->enabled == 0) {
60357429Smarkm		packet_init_compression();
604197679Sdes		if (mode == MODE_OUT)
60557429Smarkm			buffer_compress_init_send(6);
606162852Sdes		else
60757429Smarkm			buffer_compress_init_recv();
608197679Sdes		comp->enabled = 1;
609197679Sdes	}
610197679Sdes}
611197679Sdes
612197679Sdes/*
613197679Sdes * Finalize packet in SSH2 format (compress, mac, encrypt, enqueue)
61492555Sdes */
61557429Smarkmstatic void
616197679Sdespacket_send2(void)
61757429Smarkm{
618162852Sdes	u_char type, *cp, *macbuf = NULL;
61960573Skris	u_char padlen, pad;
62060573Skris	u_int packet_length = 0;
62160573Skris	u_int i, len;
622197679Sdes	u_int32_t rand = 0;
62360573Skris	Enc *enc   = NULL;
624162852Sdes	Mac *mac   = NULL;
62560573Skris	Comp *comp = NULL;
62692555Sdes	int block_size;
62760573Skris
628197679Sdes	if (newkeys[MODE_OUT] != NULL) {
62960573Skris		enc  = &newkeys[MODE_OUT]->enc;
630162852Sdes		mac  = &newkeys[MODE_OUT]->mac;
63157429Smarkm		comp = &newkeys[MODE_OUT]->comp;
63257429Smarkm	}
63357429Smarkm	block_size = enc ? enc->block_size : 8;
634197679Sdes
63557429Smarkm	cp = buffer_ptr(&outgoing_packet);
636162852Sdes	type = cp[5];
63760573Skris
63860573Skris#ifdef PACKET_DEBUG
63960573Skris	fprintf(stderr, "plain:     ");
640197679Sdes	buffer_dump(&outgoing_packet);
64160573Skris#endif
64257429Smarkm
643221420Sdes	if (comp && comp->enabled) {
644221420Sdes		len = buffer_len(&outgoing_packet);
645221420Sdes		/* skip header, compress only payload */
646221420Sdes		buffer_consume(&outgoing_packet, 5);
647221420Sdes		buffer_clear(&compression_buffer);
648221420Sdes		buffer_compress(&outgoing_packet, &compression_buffer);
649221420Sdes		buffer_clear(&outgoing_packet);
650221420Sdes		buffer_append(&outgoing_packet, "\0\0\0\0\0", 5);
65157429Smarkm		buffer_append(&outgoing_packet, buffer_ptr(&compression_buffer),
65257429Smarkm		    buffer_len(&compression_buffer));
65357429Smarkm		DBG(debug("compression: raw %d compressed %d", len,
65457429Smarkm		    buffer_len(&outgoing_packet)));
65557429Smarkm	}
65692555Sdes
65776259Sgreen	/* sizeof (packet_len + pad_len + payload) */
65857429Smarkm	len = buffer_len(&outgoing_packet);
65992555Sdes
66057429Smarkm	/*
66176259Sgreen	 * calc size of padding, alloc space, get random data,
662137015Sdes	 * minimum padding is 4 bytes
66357429Smarkm	 */
66457429Smarkm	padlen = block_size - (len % block_size);
66557429Smarkm	if (padlen < 4)
66657429Smarkm		padlen += block_size;
66757429Smarkm	if (extra_pad) {
668197679Sdes		/* will wrap if extra_pad+padlen > 255 */
669197679Sdes		extra_pad  = roundup(extra_pad, block_size);
67057429Smarkm		pad = extra_pad - ((len + padlen) % extra_pad);
671197679Sdes		debug3("packet_send2: adding %d (len %d padlen %d extra_pad %d)",
67257429Smarkm		    pad, len, padlen, extra_pad);
673197679Sdes		padlen += pad;
674197679Sdes		extra_pad = 0;
675197679Sdes	}
676197679Sdes	cp = buffer_append_space(&outgoing_packet, padlen);
677197679Sdes	if (enc && !send_context.plaintext) {
678197679Sdes		/* random padding */
679197679Sdes		for (i = 0; i < padlen; i++) {
680197679Sdes			if (i % 4 == 0)
68157429Smarkm				rand = arc4random();
68257429Smarkm			cp[i] = rand & 0xff;
683197679Sdes			rand >>= 8;
68457429Smarkm		}
68560573Skris	} else {
68657429Smarkm		/* clear padding */
687197679Sdes		memset(cp, 0, padlen);
688197679Sdes	}
68957429Smarkm	/* packet_length includes payload, padding and padding length field */
69057429Smarkm	packet_length = buffer_len(&outgoing_packet) - 4;
691137015Sdes	cp = buffer_ptr(&outgoing_packet);
692137015Sdes	PUT_32BIT(cp, packet_length);
693137015Sdes	cp[4] = padlen;
69457429Smarkm	DBG(debug("send: len %d (includes padlen %d)", packet_length+4, padlen));
69557429Smarkm
696197679Sdes	/* compute MAC over seqnr and packet(length fields, payload, padding) */
69757429Smarkm	if (mac && mac->enabled) {
69857429Smarkm		macbuf = mac_compute(mac, send_seqnr,
699197679Sdes		    buffer_ptr(&outgoing_packet),
700197679Sdes		    buffer_len(&outgoing_packet));
701162852Sdes		DBG(debug("done calc MAC out #%d", send_seqnr));
702197679Sdes	}
70357429Smarkm	/* encrypt packet and append to output buffer. */
70457429Smarkm	cp = buffer_append_space(&output, buffer_len(&outgoing_packet));
70557429Smarkm	cipher_crypt(&send_context, cp, buffer_ptr(&outgoing_packet),
706197679Sdes	    buffer_len(&outgoing_packet));
70757429Smarkm	/* append unencrypted MAC */
70857429Smarkm	if (mac && mac->enabled)
70957429Smarkm		buffer_append(&output, (char *)macbuf, mac->mac_len);
710162852Sdes#ifdef PACKET_DEBUG
711197679Sdes	fprintf(stderr, "encrypted: ");
712197679Sdes	buffer_dump(&output);
713197679Sdes#endif
714197679Sdes	/* increment sequence number for outgoing packets */
715197679Sdes	if (++send_seqnr == 0)
716248619Sdes		log("outgoing seqnr wraps around");
71757429Smarkm	buffer_clear(&outgoing_packet);
71857429Smarkm
71957429Smarkm	if (type == SSH2_MSG_NEWKEYS)
720197679Sdes		set_newkeys(MODE_OUT);
72157429Smarkm}
722197679Sdes
723197679Sdesvoid
724197679Sdespacket_send(void)
725197679Sdes{
72657429Smarkm	if (compat20)
72757429Smarkm		packet_send2();
728157016Sdes	else
72957429Smarkm		packet_send1();
73057429Smarkm	DBG(debug("packet_send done"));
73157429Smarkm}
73257429Smarkm
73357429Smarkm/*
73498675Sdes * Waits until a packet has been received, and returns its type.  Note that
73576259Sgreen * no other data is processed until this returns, so this function should not
73676259Sgreen * be used during the interactive session.
73776259Sgreen */
73876259Sgreen
73976259Sgreenint
74076259Sgreenpacket_read_seqnr(u_int32_t *seqnr_p)
741124208Sdes{
742137015Sdes	int type, len;
74376259Sgreen	fd_set *setp;
744113908Sdes	char buf[8192];
74576259Sgreen	DBG(debug("packet_read()"));
74692555Sdes
747197679Sdes	setp = (fd_set *)xmalloc(howmany(connection_in+1, NFDBITS) *
748137015Sdes	    sizeof(fd_mask));
749197679Sdes
750197679Sdes	/* Since we are blocking, ensure that all written packets have been sent. */
75192555Sdes	packet_write_wait();
752197679Sdes
753137015Sdes	/* Stay in the loop until we have received a complete packet. */
754197679Sdes	for (;;) {
755197679Sdes		/* Try to read a packet from the buffer. */
75692555Sdes		type = packet_read_poll_seqnr(seqnr_p);
757197679Sdes		if (!compat20 && (
758113908Sdes		    type == SSH_SMSG_SUCCESS
75992555Sdes		    || type == SSH_SMSG_FAILURE
760197679Sdes		    || type == SSH_CMSG_EOF
761197679Sdes		    || type == SSH_CMSG_EXIT_CONFIRMATION))
762197679Sdes			packet_check_eom();
763181111Sdes		/* If we got a packet, return it. */
764248619Sdes		if (type != SSH_MSG_NONE) {
765248619Sdes			xfree(setp);
766248619Sdes			return type;
76776259Sgreen		}
76876259Sgreen		/*
76976259Sgreen		 * Otherwise, wait for some data to arrive, add it to the
77076259Sgreen		 * buffer, and try again.
77176259Sgreen		 */
77276259Sgreen		memset(setp, 0, howmany(connection_in + 1, NFDBITS) *
773197679Sdes		    sizeof(fd_mask));
77476259Sgreen		FD_SET(connection_in, setp);
775197679Sdes
776197679Sdes		/* Wait for some data to arrive. */
77776259Sgreen		while (select(connection_in + 1, setp, NULL, NULL, NULL) == -1 &&
778197679Sdes		    (errno == EAGAIN || errno == EINTR))
779197679Sdes			;
780197679Sdes
781248619Sdes		/* Read data from the socket. */
78276259Sgreen		len = read(connection_in, buf, sizeof(buf));
78376259Sgreen		if (len == 0) {
78492555Sdes			log("Connection closed by %.200s", get_remote_ipaddr());
785248619Sdes			fatal_cleanup();
78698675Sdes		}
78798675Sdes		if (len < 0)
788181111Sdes			fatal("Read from socket failed: %.100s", strerror(errno));
789181111Sdes		/* Append it to the buffer. */
790149749Sdes		packet_process_incoming(buf, len);
791197679Sdes	}
792197679Sdes	/* NOTREACHED */
79376259Sgreen}
79476259Sgreen
79576259Sgreenint
79676259Sgreenpacket_read(void)
79776259Sgreen{
79876259Sgreen	return packet_read_seqnr(NULL);
79976259Sgreen}
800124208Sdes
801124208Sdes/*
802124208Sdes * Waits until a packet has been received, verifies that its type matches
803124208Sdes * that given, and gives a fatal error and exits if there is a mismatch.
804124208Sdes */
805124208Sdes
806124208Sdesvoid
807124208Sdespacket_read_expect(int expected_type)
808197679Sdes{
809197679Sdes	int type;
810197679Sdes
81176259Sgreen	type = packet_read();
81276259Sgreen	if (type != expected_type)
81357429Smarkm		packet_disconnect("Protocol error: expected packet type %d, got %d",
814149749Sdes		    expected_type, type);
815162852Sdes}
816149749Sdes
817149749Sdes/* Checks if a full packet is available in the data received so far via
818149749Sdes * packet_process_incoming.  If so, reads the packet; otherwise returns
819149749Sdes * SSH_MSG_NONE.  This does not wait for data from the connection.
820149749Sdes *
821149749Sdes * SSH_MSG_DISCONNECT is handled specially here.  Also,
822149749Sdes * SSH_MSG_IGNORE messages are skipped by this function and are never returned
823149749Sdes * to higher levels.
824149749Sdes */
825149749Sdes
826149749Sdesstatic int
827149749Sdespacket_read_poll1(void)
828197679Sdes{
829149749Sdes	u_int len, padded_len;
830162852Sdes	u_char *cp, type;
831197679Sdes	u_int checksum, stored_checksum;
832162852Sdes
833197679Sdes	/* Check if input size is less than minimum packet size. */
834149749Sdes	if (buffer_len(&input) < 4 + 8)
835149749Sdes		return SSH_MSG_NONE;
836149749Sdes	/* Get length of incoming packet. */
837149749Sdes	cp = buffer_ptr(&input);
838149749Sdes	len = GET_32BIT(cp);
839149749Sdes	if (len < 1 + 2 + 2 || len > 256 * 1024)
840149749Sdes		packet_disconnect("Bad packet length %d.", len);
841149749Sdes	padded_len = (len + 8) & ~7;
842149749Sdes
843149749Sdes	/* Check if the packet has been entirely received. */
844149749Sdes	if (buffer_len(&input) < 4 + padded_len)
845149749Sdes		return SSH_MSG_NONE;
84660573Skris
84760573Skris	/* The entire packet is in buffer. */
84892555Sdes
849124208Sdes	/* Consume packet length. */
85060573Skris	buffer_consume(&input, 4);
85192555Sdes
852248619Sdes	/*
853248619Sdes	 * Cryptographic attack detector for ssh
854137015Sdes	 * (C)1998 CORE-SDI, Buenos Aires Argentina
85560573Skris	 * Ariel Futoransky(futo@core-sdi.com)
85660573Skris	 */
85760573Skris	if (!receive_context.plaintext &&
85860573Skris	    detect_attack(buffer_ptr(&input), padded_len, NULL) == DEATTACK_DETECTED)
85960573Skris		packet_disconnect("crc32 compensation attack: network attack detected");
860197679Sdes
861197679Sdes	/* Decrypt data to incoming_packet. */
862197679Sdes	buffer_clear(&incoming_packet);
863197679Sdes	cp = buffer_append_space(&incoming_packet, padded_len);
864248619Sdes	cipher_crypt(&receive_context, cp, buffer_ptr(&input), padded_len);
865248619Sdes
866248619Sdes	buffer_consume(&input, padded_len);
86760573Skris
86892555Sdes#ifdef PACKET_DEBUG
869248619Sdes	fprintf(stderr, "read_poll plain: ");
87060573Skris	buffer_dump(&incoming_packet);
871197679Sdes#endif
87292555Sdes
87360573Skris	/* Compute packet checksum. */
87460573Skris	checksum = ssh_crc32(buffer_ptr(&incoming_packet),
87560573Skris	    buffer_len(&incoming_packet) - 4);
876197679Sdes
87760573Skris	/* Skip padding. */
87860573Skris	buffer_consume(&incoming_packet, 8 - len % 8);
87960573Skris
880197679Sdes	/* Test check bytes. */
88160573Skris	if (len != buffer_len(&incoming_packet))
882197679Sdes		packet_disconnect("packet_read_poll1: len %d != buffer_len %d.",
883197679Sdes		    len, buffer_len(&incoming_packet));
884197679Sdes
885197679Sdes	cp = (u_char *)buffer_ptr(&incoming_packet) + len - 4;
886197679Sdes	stored_checksum = GET_32BIT(cp);
887197679Sdes	if (checksum != stored_checksum)
888197679Sdes		packet_disconnect("Corrupted check bytes on input.");
889197679Sdes	buffer_consume_end(&incoming_packet, 4);
890197679Sdes
89160573Skris	if (packet_compression) {
892197679Sdes		buffer_clear(&compression_buffer);
89360573Skris		buffer_uncompress(&incoming_packet, &compression_buffer);
89460573Skris		buffer_clear(&incoming_packet);
89560573Skris		buffer_append(&incoming_packet, buffer_ptr(&compression_buffer),
896197679Sdes		    buffer_len(&compression_buffer));
89760573Skris	}
89860573Skris	type = buffer_get_char(&incoming_packet);
89960573Skris	return type;
90060573Skris}
90160573Skris
902248619Sdesstatic int
90360573Skrispacket_read_poll2(u_int32_t *seqnr_p)
90460573Skris{
90560573Skris	static u_int packet_length = 0;
906197679Sdes	u_int padlen, need;
90792555Sdes	u_char *macbuf, *cp, type;
908197679Sdes	int maclen, block_size;
909197679Sdes	Enc *enc   = NULL;
910197679Sdes	Mac *mac   = NULL;
911197679Sdes	Comp *comp = NULL;
91298675Sdes
913197679Sdes	if (newkeys[MODE_IN] != NULL) {
91492555Sdes		enc  = &newkeys[MODE_IN]->enc;
915197679Sdes		mac  = &newkeys[MODE_IN]->mac;
91692555Sdes		comp = &newkeys[MODE_IN]->comp;
917197679Sdes	}
918197679Sdes	maclen = mac && mac->enabled ? mac->mac_len : 0;
91960573Skris	block_size = enc ? enc->block_size : 8;
92060573Skris
92160573Skris	if (packet_length == 0) {
922137015Sdes		/*
923137015Sdes		 * check if input size is less than the cipher block size,
924137015Sdes		 * decrypt first block and extract length of incoming packet
92560573Skris		 */
92660573Skris		if (buffer_len(&input) < block_size)
92760573Skris			return SSH_MSG_NONE;
92860573Skris		buffer_clear(&incoming_packet);
92960573Skris		cp = buffer_append_space(&incoming_packet, block_size);
930248619Sdes		cipher_crypt(&receive_context, cp, buffer_ptr(&input),
931248619Sdes		    block_size);
932248619Sdes		cp = buffer_ptr(&incoming_packet);
93360573Skris		packet_length = GET_32BIT(cp);
934248619Sdes		if (packet_length < 1 + 4 || packet_length > 256 * 1024) {
93592555Sdes			buffer_dump(&incoming_packet);
936248619Sdes			packet_disconnect("Bad packet length %d.", packet_length);
937248619Sdes		}
93860573Skris		DBG(debug("input: packet len %d", packet_length+4));
93960573Skris		buffer_consume(&input, block_size);
940248619Sdes	}
941197679Sdes	/* we have a partial packet of block_size bytes */
942248619Sdes	need = 4 + packet_length - block_size;
943197679Sdes	DBG(debug("partial packet %d, need %d, maclen %d", block_size,
94460573Skris	    need, maclen));
94560573Skris	if (need % block_size != 0)
946248619Sdes		fatal("padding error: need %d block %d mod %d",
947197679Sdes		    need, block_size, need % block_size);
948197679Sdes	/*
949248619Sdes	 * check if the entire packet has been received and
95060573Skris	 * decrypt into incoming_packet
951248619Sdes	 */
952248619Sdes	if (buffer_len(&input) < need + maclen)
953248619Sdes		return SSH_MSG_NONE;
954248619Sdes#ifdef PACKET_DEBUG
955248619Sdes	fprintf(stderr, "read_poll enc/full: ");
956248619Sdes	buffer_dump(&input);
957248619Sdes#endif
958248619Sdes	cp = buffer_append_space(&incoming_packet, need);
959197679Sdes	cipher_crypt(&receive_context, cp, buffer_ptr(&input), need);
960248619Sdes	buffer_consume(&input, need);
96160573Skris	/*
96260573Skris	 * compute MAC over seqnr and packet,
963197679Sdes	 * increment sequence number for incoming packet
96460573Skris	 */
96560573Skris	if (mac && mac->enabled) {
966197679Sdes		macbuf = mac_compute(mac, read_seqnr,
967124208Sdes		    buffer_ptr(&incoming_packet),
968197679Sdes		    buffer_len(&incoming_packet));
969124208Sdes		if (memcmp(macbuf, buffer_ptr(&input), mac->mac_len) != 0)
970124208Sdes			packet_disconnect("Corrupted MAC on input.");
971248619Sdes		DBG(debug("MAC #%d ok", read_seqnr));
972248619Sdes		buffer_consume(&input, mac->mac_len);
973197679Sdes	}
97460573Skris	if (seqnr_p != NULL)
97576259Sgreen		*seqnr_p = read_seqnr;
97676259Sgreen	if (++read_seqnr == 0)
977197679Sdes		log("incoming seqnr wraps around");
978149749Sdes
97960573Skris	/* get padlen */
98060573Skris	cp = buffer_ptr(&incoming_packet);
981124208Sdes	padlen = cp[4];
982124208Sdes	DBG(debug("input: padlen %d", padlen));
983124208Sdes	if (padlen < 4)
984124208Sdes		packet_disconnect("Corrupted padlen %d on input.", padlen);
985124208Sdes
986124208Sdes	/* skip packet size + padlen, discard padding */
987197679Sdes	buffer_consume(&incoming_packet, 4 + 1);
988124208Sdes	buffer_consume_end(&incoming_packet, padlen);
989124208Sdes
990124208Sdes	DBG(debug("input: len before de-compress %d", buffer_len(&incoming_packet)));
991197679Sdes	if (comp && comp->enabled) {
992240075Sdes		buffer_clear(&compression_buffer);
993240075Sdes		buffer_uncompress(&incoming_packet, &compression_buffer);
994240075Sdes		buffer_clear(&incoming_packet);
995240075Sdes		buffer_append(&incoming_packet, buffer_ptr(&compression_buffer),
996124208Sdes		    buffer_len(&compression_buffer));
997124208Sdes		DBG(debug("input: len after de-compress %d", buffer_len(&incoming_packet)));
998124208Sdes	}
999197679Sdes	/*
1000197679Sdes	 * get packet type, implies consume.
1001197679Sdes	 * return length of payload (without type field)
1002197679Sdes	 */
1003124208Sdes	type = buffer_get_char(&incoming_packet);
1004124208Sdes	if (type == SSH2_MSG_NEWKEYS)
1005124208Sdes		set_newkeys(MODE_IN);
1006124208Sdes#ifdef PACKET_DEBUG
1007124208Sdes	fprintf(stderr, "read/plain[%d]:\r\n", type);
1008124208Sdes	buffer_dump(&incoming_packet);
1009197679Sdes#endif
1010124208Sdes	/* reset for next packet */
1011124208Sdes	packet_length = 0;
1012124208Sdes	return type;
1013124208Sdes}
1014124208Sdes
1015197679Sdesint
1016197679Sdespacket_read_poll_seqnr(u_int32_t *seqnr_p)
1017124208Sdes{
1018124208Sdes	u_int reason, seqnr;
1019197679Sdes	u_char type;
1020197679Sdes	char *msg;
1021124208Sdes
1022197679Sdes	for (;;) {
1023124208Sdes		if (compat20) {
1024124208Sdes			type = packet_read_poll2(seqnr_p);
1025124208Sdes			if (type)
1026124208Sdes				DBG(debug("received packet type %d", type));
1027124208Sdes			switch (type) {
1028124208Sdes			case SSH2_MSG_IGNORE:
102960573Skris				break;
103092555Sdes			case SSH2_MSG_DEBUG:
103160573Skris				packet_get_char();
103292555Sdes				msg = packet_get_string(NULL);
103360573Skris				debug("Remote: %.900s", msg);
103460573Skris				xfree(msg);
103560573Skris				msg = packet_get_string(NULL);
103660573Skris				xfree(msg);
103760573Skris				break;
103860573Skris			case SSH2_MSG_DISCONNECT:
103960573Skris				reason = packet_get_int();
104057429Smarkm				msg = packet_get_string(NULL);
104157429Smarkm				log("Received disconnect from %s: %u: %.400s",
104257429Smarkm				    get_remote_ipaddr(), reason, msg);
104357429Smarkm				xfree(msg);
104457429Smarkm				fatal_cleanup();
104557429Smarkm				break;
104692555Sdes			case SSH2_MSG_UNIMPLEMENTED:
104757429Smarkm				seqnr = packet_get_int();
1048197679Sdes				debug("Received SSH2_MSG_UNIMPLEMENTED for %u",
104976259Sgreen				    seqnr);
105057429Smarkm				break;
1051181111Sdes			default:
1052181111Sdes				return type;
105360573Skris				break;
105457429Smarkm			}
1055197679Sdes		} else {
1056197679Sdes			type = packet_read_poll1();
105776259Sgreen			switch (type) {
105857429Smarkm			case SSH_MSG_IGNORE:
105957429Smarkm				break;
106057429Smarkm			case SSH_MSG_DEBUG:
106157429Smarkm				msg = packet_get_string(NULL);
106257429Smarkm				debug("Remote: %.900s", msg);
106357429Smarkm				xfree(msg);
106492555Sdes				break;
106592555Sdes			case SSH_MSG_DISCONNECT:
106660573Skris				msg = packet_get_string(NULL);
106757429Smarkm				log("Received disconnect from %s: %.400s",
106857429Smarkm				    get_remote_ipaddr(), msg);
106960573Skris				fatal_cleanup();
107092555Sdes				xfree(msg);
107157429Smarkm				break;
107276259Sgreen			default:
107376259Sgreen				if (type)
107457429Smarkm					DBG(debug("received packet type %d", type));
107576259Sgreen				return type;
107657429Smarkm				break;
107757429Smarkm			}
107857429Smarkm		}
107957429Smarkm	}
1080197679Sdes}
1081197679Sdes
1082197679Sdesint
108357429Smarkmpacket_read_poll(void)
1084197679Sdes{
1085197679Sdes	return packet_read_poll_seqnr(NULL);
1086181111Sdes}
1087181111Sdes
108857429Smarkm/*
1089181111Sdes * Buffers the given amount of input characters.  This is intended to be used
1090197679Sdes * together with packet_read_poll.
1091181111Sdes */
1092181111Sdes
1093181111Sdesvoid
1094197679Sdespacket_process_incoming(const char *buf, u_int len)
1095197679Sdes{
1096181111Sdes	buffer_append(&input, buf, len);
1097197679Sdes}
1098181111Sdes
1099181111Sdes/* Returns a character from the packet. */
1100197679Sdes
1101181111Sdesu_int
1102181111Sdespacket_get_char(void)
1103181111Sdes{
1104181111Sdes	char ch;
1105181111Sdes	buffer_get(&incoming_packet, &ch, 1);
1106181111Sdes	return (u_char) ch;
1107181111Sdes}
1108181111Sdes
1109181111Sdes/* Returns an integer from the packet data. */
1110181111Sdes
1111181111Sdesu_int
1112181111Sdespacket_get_int(void)
111357429Smarkm{
1114197679Sdes	return buffer_get_int(&incoming_packet);
1115197679Sdes}
1116197679Sdes
1117197679Sdes/*
1118197679Sdes * Returns an arbitrary precision integer from the packet data.  The integer
111957429Smarkm * must have been initialized before this call.
1120124208Sdes */
1121126274Sdes
112257429Smarkmvoid
112357429Smarkmpacket_get_bignum(BIGNUM * value)
112457429Smarkm{
112557429Smarkm	buffer_get_bignum(&incoming_packet, value);
112657429Smarkm}
112757429Smarkm
112857429Smarkmvoid
112957429Smarkmpacket_get_bignum2(BIGNUM * value)
113057429Smarkm{
113192555Sdes	buffer_get_bignum2(&incoming_packet, value);
113292555Sdes}
113392555Sdes
113492555Sdesvoid *
113592555Sdespacket_get_raw(int *length_ptr)
113692555Sdes{
113757429Smarkm	int bytes = buffer_len(&incoming_packet);
113857429Smarkm	if (length_ptr != NULL)
113957429Smarkm		*length_ptr = bytes;
114057429Smarkm	return buffer_ptr(&incoming_packet);
114157429Smarkm}
114257429Smarkm
114392555Sdesint
114457429Smarkmpacket_remaining(void)
114557429Smarkm{
114657429Smarkm	return buffer_len(&incoming_packet);
114792555Sdes}
114857429Smarkm
114957429Smarkm/*
115060573Skris * Returns a string from the packet data.  The string is allocated using
115157429Smarkm * xmalloc; it is the responsibility of the calling program to free it when
115257429Smarkm * no longer needed.  The length_ptr argument may be NULL, or point to an
115357429Smarkm * integer into which the length of the string is stored.
115457429Smarkm */
115557429Smarkm
115657429Smarkmvoid *
115757429Smarkmpacket_get_string(u_int *length_ptr)
115857429Smarkm{
115957429Smarkm	return buffer_get_string(&incoming_packet, length_ptr);
116057429Smarkm}
116157429Smarkm
116292555Sdes/*
116392555Sdes * Sends a diagnostic message from the server to the client.  This message
116457429Smarkm * can be sent at any time (but not while constructing another message). The
116576259Sgreen * message is printed immediately, but only if the client is being executed
116692555Sdes * in verbose mode.  These messages are primarily intended to ease debugging
116776259Sgreen * authentication problems.   The length of the formatted message must not
116857429Smarkm * exceed 1024 bytes.  This will automatically call packet_write_wait.
116957429Smarkm */
1170197679Sdes
117157429Smarkmvoid
117257429Smarkmpacket_send_debug(const char *fmt,...)
1173197679Sdes{
1174162852Sdes	char buf[1024];
117557429Smarkm	va_list args;
1176113908Sdes
117757429Smarkm	if (compat20 && (datafellows & SSH_BUG_DEBUG))
117857429Smarkm		return;
117957429Smarkm
1180197679Sdes	va_start(args, fmt);
118157429Smarkm	vsnprintf(buf, sizeof(buf), fmt, args);
118257429Smarkm	va_end(args);
118357429Smarkm
118457429Smarkm	if (compat20) {
118557429Smarkm		packet_start(SSH2_MSG_DEBUG);
1186197679Sdes		packet_put_char(0);	/* bool: always display */
118757429Smarkm		packet_put_cstring(buf);
118892555Sdes		packet_put_cstring("");
118992555Sdes	} else {
119092555Sdes		packet_start(SSH_MSG_DEBUG);
119192555Sdes		packet_put_cstring(buf);
119292555Sdes	}
1193197679Sdes	packet_send();
1194197679Sdes	packet_write_wait();
1195197679Sdes}
1196162852Sdes
1197162852Sdes/*
1198162852Sdes * Logs the error plus constructs and sends a disconnect packet, closes the
1199162852Sdes * connection, and exits.  This function never returns. The error message
1200162852Sdes * should not contain a newline.  The length of the formatted message must
1201162852Sdes * not exceed 1024 bytes.
1202162852Sdes */
1203162852Sdes
120492555Sdesvoid
120592555Sdespacket_disconnect(const char *fmt,...)
1206197679Sdes{
1207197679Sdes	char buf[1024];
1208197679Sdes	va_list args;
1209248619Sdes	static int disconnecting = 0;
121092555Sdes	if (disconnecting)	/* Guard against recursive invocations. */
1211197679Sdes		fatal("packet_disconnect called recursively.");
121257429Smarkm	disconnecting = 1;
121357429Smarkm
121457429Smarkm	/*
1215197679Sdes	 * Format the message.  Note that the caller must make sure the
121657429Smarkm	 * message is of limited size.
121757429Smarkm	 */
121857429Smarkm	va_start(args, fmt);
1219197679Sdes	vsnprintf(buf, sizeof(buf), fmt, args);
1220197679Sdes	va_end(args);
122157429Smarkm
122257429Smarkm	/* Send the disconnect message to the other side, and wait for it to get sent. */
1223197679Sdes	if (compat20) {
122457429Smarkm		packet_start(SSH2_MSG_DISCONNECT);
122557429Smarkm		packet_put_int(SSH2_DISCONNECT_PROTOCOL_ERROR);
1226197679Sdes		packet_put_cstring(buf);
122792555Sdes		packet_put_cstring("");
1228197679Sdes	} else {
122957429Smarkm		packet_start(SSH_MSG_DISCONNECT);
1230197679Sdes		packet_put_cstring(buf);
1231162852Sdes	}
123257429Smarkm	packet_send();
123357429Smarkm	packet_write_wait();
1234197679Sdes
123557429Smarkm	/* Stop listening for connections. */
1236197679Sdes	channel_close_all();
1237197679Sdes
1238197679Sdes	/* Close the connection. */
1239197679Sdes	packet_close();
1240197679Sdes
1241197679Sdes	/* Display the error locally and exit. */
1242197679Sdes	log("Disconnecting: %.100s", buf);
1243197679Sdes	fatal_cleanup();
124457429Smarkm}
1245197679Sdes
1246197679Sdes/* Checks if there is any buffered output, and tries to write some of the output. */
1247197679Sdes
1248146998Sdesvoid
1249146998Sdespacket_write_poll(void)
125092555Sdes{
125160573Skris	int len = buffer_len(&output);
125257429Smarkm	if (len > 0) {
125392555Sdes		len = write(connection_out, buffer_ptr(&output), len);
125492555Sdes		if (len <= 0) {
125560573Skris			if (errno == EAGAIN)
125676259Sgreen				return;
1257248619Sdes			else
1258248619Sdes				fatal("Write failed: %.100s", strerror(errno));
125960573Skris		}
126060573Skris		buffer_consume(&output, len);
126160573Skris	}
126257429Smarkm}
1263197679Sdes
1264192595Sdes/*
1265192595Sdes * Calls packet_write_poll repeatedly until all pending output data has been
1266197679Sdes * written.
1267197679Sdes */
1268197679Sdes
1269197679Sdesvoid
1270248619Sdespacket_write_wait(void)
1271248619Sdes{
1272248619Sdes	fd_set *setp;
127357429Smarkm
127460573Skris	setp = (fd_set *)xmalloc(howmany(connection_out + 1, NFDBITS) *
127592555Sdes	    sizeof(fd_mask));
1276248619Sdes	packet_write_poll();
127760573Skris	while (packet_have_data_to_write()) {
1278248619Sdes		memset(setp, 0, howmany(connection_out + 1, NFDBITS) *
1279248619Sdes		    sizeof(fd_mask));
1280248619Sdes		FD_SET(connection_out, setp);
1281248619Sdes		while (select(connection_out + 1, NULL, setp, NULL, NULL) == -1 &&
1282248619Sdes		    (errno == EAGAIN || errno == EINTR))
1283248619Sdes			;
1284248619Sdes		packet_write_poll();
1285248619Sdes	}
1286248619Sdes	xfree(setp);
1287248619Sdes}
1288248619Sdes
1289248619Sdes/* Returns true if there is buffered data to write to the connection. */
1290248619Sdes
1291248619Sdesint
1292248619Sdespacket_have_data_to_write(void)
129360573Skris{
129460573Skris	return buffer_len(&output) != 0;
129560573Skris}
129660573Skris
1297197679Sdes/* Returns true if there is not too much data to write to the connection. */
129860573Skris
1299197679Sdesint
1300197679Sdespacket_not_very_much_data_to_write(void)
130160573Skris{
1302197679Sdes	if (interactive_mode)
1303248619Sdes		return buffer_len(&output) < 16384;
1304197679Sdes	else
1305240075Sdes		return buffer_len(&output) < 128 * 1024;
1306197679Sdes}
1307197679Sdes
1308197679Sdes/* Informs that the current session is interactive.  Sets IP flags for that. */
1309124208Sdes
1310197679Sdesvoid
1311124208Sdespacket_set_interactive(int interactive)
1312197679Sdes{
1313197679Sdes	static int called = 0;
1314192595Sdes#if defined(IP_TOS) && !defined(IP_TOS_IS_BROKEN)
1315192595Sdes	int lowdelay = IPTOS_LOWDELAY;
131660573Skris	int throughput = IPTOS_THROUGHPUT;
1317197679Sdes#endif
131860573Skris
1319248619Sdes	if (called)
1320248619Sdes		return;
1321248619Sdes	called = 1;
1322248619Sdes
1323248619Sdes	/* Record that we are in interactive mode. */
1324248619Sdes	interactive_mode = interactive;
1325248619Sdes
1326248619Sdes	/* Only set socket options if using a socket.  */
1327248619Sdes	if (!packet_connection_is_on_socket())
1328248619Sdes		return;
1329248619Sdes	/*
1330248619Sdes	 * IPTOS_LOWDELAY and IPTOS_THROUGHPUT are IPv4 only
1331248619Sdes	 */
1332192595Sdes	if (interactive) {
1333192595Sdes		/*
133460573Skris		 * Set IP options for an interactive connection.  Use
1335197679Sdes		 * IPTOS_LOWDELAY and TCP_NODELAY.
1336192595Sdes		 */
1337192595Sdes#if defined(IP_TOS) && !defined(IP_TOS_IS_BROKEN)
1338192595Sdes		if (packet_connection_is_ipv4()) {
133960573Skris			if (setsockopt(connection_in, IPPROTO_IP, IP_TOS,
134060573Skris			    &lowdelay, sizeof(lowdelay)) < 0)
1341248619Sdes				error("setsockopt IPTOS_LOWDELAY: %.100s",
1342248619Sdes				    strerror(errno));
1343248619Sdes		}
1344248619Sdes#endif
1345248619Sdes		set_nodelay(connection_in);
134660573Skris	} else if (packet_connection_is_ipv4()) {
1347248619Sdes		/*
134860573Skris		 * Set IP options for a non-interactive connection.  Use
134960573Skris		 * IPTOS_THROUGHPUT.
135060573Skris		 */
1351197679Sdes#if defined(IP_TOS) && !defined(IP_TOS_IS_BROKEN)
135260573Skris		if (setsockopt(connection_in, IPPROTO_IP, IP_TOS, &throughput,
1353248619Sdes		    sizeof(throughput)) < 0)
1354248619Sdes			error("setsockopt IPTOS_THROUGHPUT: %.100s", strerror(errno));
1355248619Sdes#endif
1356248619Sdes	}
1357248619Sdes}
1358197679Sdes
1359248619Sdes/* Returns true if the current connection is interactive. */
1360248619Sdes
136160573Skrisint
136260573Skrispacket_is_interactive(void)
136360573Skris{
136460573Skris	return interactive_mode;
136560573Skris}
1366248619Sdes
1367248619Sdesint
1368248619Sdespacket_set_maxsize(int s)
1369248619Sdes{
1370215116Sdes	static int called = 0;
1371197679Sdes	if (called) {
1372192595Sdes		log("packet_set_maxsize: called twice: old %d new %d",
1373192595Sdes		    max_packet_size, s);
1374192595Sdes		return -1;
1375197679Sdes	}
1376192595Sdes	if (s < 4 * 1024 || s > 1024 * 1024) {
1377192595Sdes		log("packet_set_maxsize: bad size %d", s);
1378192595Sdes		return -1;
1379192595Sdes	}
1380197679Sdes	called = 1;
1381197679Sdes	debug("packet_set_maxsize: setting to %d", s);
138260573Skris	max_packet_size = s;
1383192595Sdes	return s;
138492555Sdes}
1385197679Sdes
1386197679Sdes/* roundup current message to pad bytes */
1387124208Sdesvoid
1388197679Sdespacket_add_padding(u_char pad)
1389124208Sdes{
1390124208Sdes	extra_pad = pad;
1391197679Sdes}
1392197679Sdes
139360573Skris/*
139460573Skris * 9.2.  Ignored Data Message
1395197679Sdes *
139692555Sdes *   byte      SSH_MSG_IGNORE
139760573Skris *   string    data
139860573Skris *
139960573Skris * All implementations MUST understand (and ignore) this message at any
140060573Skris * time (after receiving the protocol version). No implementation is
140160573Skris * required to send them. This message can be used as an additional
1402197679Sdes * protection measure against advanced traffic analysis techniques.
1403197679Sdes */
140460573Skrisvoid
1405197679Sdespacket_send_ignore(int nbytes)
1406197679Sdes{
140760573Skris	u_int32_t rand = 0;
1408197679Sdes	int i;
1409197679Sdes
1410197679Sdes	packet_start(compat20 ? SSH2_MSG_IGNORE : SSH_MSG_IGNORE);
1411197679Sdes	packet_put_int(nbytes);
1412197679Sdes	for (i = 0; i < nbytes; i++) {
1413197679Sdes		if (i % 4 == 0)
1414197679Sdes			rand = arc4random();
1415106121Sdes		packet_put_char(rand & 0xff);
1416197679Sdes		rand >>= 8;
141760573Skris	}
141860573Skris}
141960573Skris