/*
 * Dropbear - a SSH2 server
 * 
 * Copyright (c) 2002,2003 Matt Johnston
 * All rights reserved.
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 * 
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE. */

#include "includes.h"
#include "packet.h"
#include "session.h"
#include "dbutil.h"
#include "ssh.h"
#include "algo.h"
#include "buffer.h"
#include "kex.h"
#include "dbrandom.h"
#include "service.h"
#include "auth.h"
#include "channel.h"

static int read_packet_init();
static void make_mac(unsigned int seqno, const struct key_context_directional * key_state,
		buffer * clear_buf, unsigned int clear_len, 
		unsigned char *output_mac);
static int checkmac();

/* For exact details see http://www.zlib.net/zlib_tech.html
 * 5 bytes per 16kB block, plus 6 bytes for the stream.
 * We might allocate 5 unnecessary bytes here if it's an
 * exact multiple. */
#define ZLIB_COMPRESS_EXPANSION (((RECV_MAX_PAYLOAD_LEN/16384)+1)*5 + 6)
#define ZLIB_DECOMPRESS_INCR 1024
#ifndef DISABLE_ZLIB
static buffer* buf_decompress(buffer* buf, unsigned int len);
static void buf_compress(buffer * dest, buffer * src, unsigned int len);
#endif

/* non-blocking function writing out a current encrypted packet */
void write_packet() {

	int len, written;
	buffer * writebuf = NULL;
	unsigned packet_type;
#ifdef HAVE_WRITEV
	struct iovec *iov = NULL;
	int i;
	struct Link *l;
	int iov_max_count;
#endif
	
	TRACE2(("enter write_packet"))
	dropbear_assert(!isempty(&ses.writequeue));

#if defined(HAVE_WRITEV) && (defined(IOV_MAX) || defined(UIO_MAXIOV))

#ifndef IOV_MAX
#define IOV_MAX UIO_MAXIOV
#endif

	/* Make sure the size of the iov is below the maximum allowed by the OS. */
	iov_max_count = ses.writequeue.count;
	if (iov_max_count > IOV_MAX)
	{
		iov_max_count = IOV_MAX;
	}

	iov = m_malloc(sizeof(*iov) * iov_max_count);
	for (l = ses.writequeue.head, i = 0; l; l = l->link, i++)
	{
		writebuf = (buffer*)l->item;
		packet_type = writebuf->data[writebuf->len-1];
		len = writebuf->len - 1 - writebuf->pos;
		dropbear_assert(len > 0);
		TRACE2(("write_packet writev #%d  type %d len %d/%d", i, packet_type,
				len, writebuf->len-1))
		iov[i].iov_base = buf_getptr(writebuf, len);
		iov[i].iov_len = len;
	}
	/* This may return EAGAIN. The main loop sometimes
	calls write_packet() without bothering to test with select() since
	it's likely to be necessary */
	written = writev(ses.sock_out, iov, iov_max_count);
	if (written < 0) {
		if (errno == EINTR || errno == EAGAIN) {
			m_free(iov);
			TRACE2(("leave write_packet: EINTR"))
			return;
		} else {
			dropbear_exit("Error writing: %s", strerror(errno));
		}
	}

	if (written == 0) {
		ses.remoteclosed();
	}

	while (written > 0) {
		writebuf = (buffer*)examine(&ses.writequeue);
		len = writebuf->len - 1 - writebuf->pos;
		if (len > written) {
			/* partial buffer write */
			buf_incrpos(writebuf, written);
			written = 0;
		} else {
			written -= len;
			dequeue(&ses.writequeue);
			buf_free(writebuf);
		}
	}

	m_free(iov);
#else /* No writev () */
	/* Get the next buffer in the queue of encrypted packets to write*/
	writebuf = (buffer*)examine(&ses.writequeue);

	/* The last byte of the buffer is not to be transmitted, but is 
	 * a cleartext packet_type indicator */
	packet_type = writebuf->data[writebuf->len-1];
	len = writebuf->len - 1 - writebuf->pos;
	dropbear_assert(len > 0);
	/* Try to write as much as possible */
	written = write(ses.sock_out, buf_getptr(writebuf, len), len);

	if (written < 0) {
		if (errno == EINTR || errno == EAGAIN) {
			TRACE2(("leave writepacket: EINTR"))
			return;
		} else {
			dropbear_exit("Error writing: %s", strerror(errno));
		}
	} 

	if (written == 0) {
		ses.remoteclosed();
	}

	if (written == len) {
		/* We've finished with the packet, free it */
		dequeue(&ses.writequeue);
		buf_free(writebuf);
		writebuf = NULL;
	} else {
		/* More packet left to write, leave it in the queue for later */
		buf_incrpos(writebuf, written);
	}
#endif /* writev */

	TRACE2(("leave write_packet"))
}

/* Non-blocking function reading available portion of a packet into the
 * ses's buffer, decrypting the length if encrypted, decrypting the
 * full portion if possible */
void read_packet() {

	int len;
	unsigned int maxlen;
	unsigned char blocksize;

	TRACE2(("enter read_packet"))
	blocksize = ses.keys->recv.algo_crypt->blocksize;
	
	if (ses.readbuf == NULL || ses.readbuf->len < blocksize) {
		int ret;
		/* In the first blocksize of a packet */

		/* Read the first blocksize of the packet, so we can decrypt it and
		 * find the length of the whole packet */
		ret = read_packet_init();

		if (ret == DROPBEAR_FAILURE) {
			/* didn't read enough to determine the length */
			TRACE2(("leave read_packet: packetinit done"))
			return;
		}
	}

	/* Attempt to read the remainder of the packet, note that there
	 * mightn't be any available (EAGAIN) */
	maxlen = ses.readbuf->len - ses.readbuf->pos;
	if (maxlen == 0) {
		/* Occurs when the packet is only a single block long and has all
		 * been read in read_packet_init().  Usually means that MAC is disabled
		 */
		len = 0;
	} else {
		len = read(ses.sock_in, buf_getptr(ses.readbuf, maxlen), maxlen);

		if (len == 0) {
			ses.remoteclosed();
		}

		if (len < 0) {
			if (errno == EINTR || errno == EAGAIN) {
				TRACE2(("leave read_packet: EINTR or EAGAIN"))
				return;
			} else {
				dropbear_exit("Error reading: %s", strerror(errno));
			}
		}

		buf_incrpos(ses.readbuf, len);
	}

	if ((unsigned int)len == maxlen) {
		/* The whole packet has been read */
		decrypt_packet();
		/* The main select() loop process_packet() to
		 * handle the packet contents... */
	}
	TRACE2(("leave read_packet"))
}

/* Function used to read the initial portion of a packet, and determine the
 * length. Only called during the first BLOCKSIZE of a packet. */
/* Returns DROPBEAR_SUCCESS if the length is determined, 
 * DROPBEAR_FAILURE otherwise */
static int read_packet_init() {

	unsigned int maxlen;
	int slen;
	unsigned int len;
	unsigned int blocksize;
	unsigned int macsize;


	blocksize = ses.keys->recv.algo_crypt->blocksize;
	macsize = ses.keys->recv.algo_mac->hashsize;

	if (ses.readbuf == NULL) {
		/* start of a new packet */
		ses.readbuf = buf_new(INIT_READBUF);
	}

	maxlen = blocksize - ses.readbuf->pos;
			
	/* read the rest of the packet if possible */
	slen = read(ses.sock_in, buf_getwriteptr(ses.readbuf, maxlen),
			maxlen);
	if (slen == 0) {
		ses.remoteclosed();
	}
	if (slen < 0) {
		if (errno == EINTR || errno == EAGAIN) {
			TRACE2(("leave read_packet_init: EINTR"))
			return DROPBEAR_FAILURE;
		}
		dropbear_exit("Error reading: %s", strerror(errno));
	}

	buf_incrwritepos(ses.readbuf, slen);

	if ((unsigned int)slen != maxlen) {
		/* don't have enough bytes to determine length, get next time */
		return DROPBEAR_FAILURE;
	}

	/* now we have the first block, need to get packet length, so we decrypt
	 * the first block (only need first 4 bytes) */
	buf_setpos(ses.readbuf, 0);
	if (ses.keys->recv.crypt_mode->decrypt(buf_getptr(ses.readbuf, blocksize), 
				buf_getwriteptr(ses.readbuf, blocksize),
				blocksize,
				&ses.keys->recv.cipher_state) != CRYPT_OK) {
		dropbear_exit("Error decrypting");
	}
	len = buf_getint(ses.readbuf) + 4 + macsize;

	TRACE2(("packet size is %d, block %d mac %d", len, blocksize, macsize))


	/* check packet length */
	if ((len > RECV_MAX_PACKET_LEN) ||
		(len < MIN_PACKET_LEN + macsize) ||
		((len - macsize) % blocksize != 0)) {
		dropbear_exit("Integrity error (bad packet size %d)", len);
	}

	if (len > ses.readbuf->size) {
		buf_resize(ses.readbuf, len);		
	}
	buf_setlen(ses.readbuf, len);
	buf_setpos(ses.readbuf, blocksize);
	return DROPBEAR_SUCCESS;
}

/* handle the received packet */
void decrypt_packet() {

	unsigned char blocksize;
	unsigned char macsize;
	unsigned int padlen;
	unsigned int len;

	TRACE2(("enter decrypt_packet"))
	blocksize = ses.keys->recv.algo_crypt->blocksize;
	macsize = ses.keys->recv.algo_mac->hashsize;

	ses.kexstate.datarecv += ses.readbuf->len;

	/* we've already decrypted the first blocksize in read_packet_init */
	buf_setpos(ses.readbuf, blocksize);

	/* decrypt it in-place */
	len = ses.readbuf->len - macsize - ses.readbuf->pos;
	if (ses.keys->recv.crypt_mode->decrypt(
				buf_getptr(ses.readbuf, len), 
				buf_getwriteptr(ses.readbuf, len),
				len,
				&ses.keys->recv.cipher_state) != CRYPT_OK) {
		dropbear_exit("Error decrypting");
	}
	buf_incrpos(ses.readbuf, len);

	/* check the hmac */
	if (checkmac() != DROPBEAR_SUCCESS) {
		dropbear_exit("Integrity error");
	}

	/* get padding length */
	buf_setpos(ses.readbuf, PACKET_PADDING_OFF);
	padlen = buf_getbyte(ses.readbuf);
		
	/* payload length */
	/* - 4 - 1 is for LEN and PADLEN values */
	len = ses.readbuf->len - padlen - 4 - 1 - macsize;
	if ((len > RECV_MAX_PAYLOAD_LEN+ZLIB_COMPRESS_EXPANSION) || (len < 1)) {
		dropbear_exit("Bad packet size %d", len);
	}

	buf_setpos(ses.readbuf, PACKET_PAYLOAD_OFF);

#ifndef DISABLE_ZLIB
	if (is_compress_recv()) {
		/* decompress */
		ses.payload = buf_decompress(ses.readbuf, len);
	} else 
#endif
	{
		/* copy payload */
		ses.payload = buf_new(len);
		memcpy(ses.payload->data, buf_getptr(ses.readbuf, len), len);
		buf_incrlen(ses.payload, len);
	}

	buf_free(ses.readbuf);
	ses.readbuf = NULL;
	buf_setpos(ses.payload, 0);

	ses.recvseq++;

	TRACE2(("leave decrypt_packet"))
}

/* Checks the mac at the end of a decrypted readbuf.
 * Returns DROPBEAR_SUCCESS or DROPBEAR_FAILURE */
static int checkmac() {

	unsigned char mac_bytes[MAX_MAC_LEN];
	unsigned int mac_size, contents_len;
	
	mac_size = ses.keys->recv.algo_mac->hashsize;
	contents_len = ses.readbuf->len - mac_size;

	buf_setpos(ses.readbuf, 0);
	make_mac(ses.recvseq, &ses.keys->recv, ses.readbuf, contents_len, mac_bytes);

	/* compare the hash */
	buf_setpos(ses.readbuf, contents_len);
	if (constant_time_memcmp(mac_bytes, buf_getptr(ses.readbuf, mac_size), mac_size) != 0) {
		return DROPBEAR_FAILURE;
	} else {
		return DROPBEAR_SUCCESS;
	}
}

#ifndef DISABLE_ZLIB
/* returns a pointer to a newly created buffer */
static buffer* buf_decompress(buffer* buf, unsigned int len) {

	int result;
	buffer * ret;
	z_streamp zstream;

	zstream = ses.keys->recv.zstream;
	ret = buf_new(len);

	zstream->avail_in = len;
	zstream->next_in = buf_getptr(buf, len);

	/* decompress the payload, incrementally resizing the output buffer */
	while (1) {

		zstream->avail_out = ret->size - ret->pos;
		zstream->next_out = buf_getwriteptr(ret, zstream->avail_out);

		result = inflate(zstream, Z_SYNC_FLUSH);

		buf_setlen(ret, ret->size - zstream->avail_out);
		buf_setpos(ret, ret->len);

		if (result != Z_BUF_ERROR && result != Z_OK) {
			dropbear_exit("zlib error");
		}

		if (zstream->avail_in == 0 &&
		   		(zstream->avail_out != 0 || result == Z_BUF_ERROR)) {
			/* we can only exit if avail_out hasn't all been used,
			 * and there's no remaining input */
			return ret;
		}

		if (zstream->avail_out == 0) {
			int new_size = 0;
			if (ret->size >= RECV_MAX_PAYLOAD_LEN) {
				/* Already been increased as large as it can go,
				 * yet didn't finish up the decompression */
				dropbear_exit("bad packet, oversized decompressed");
			}
			new_size = MIN(RECV_MAX_PAYLOAD_LEN, ret->size + ZLIB_DECOMPRESS_INCR);
			buf_resize(ret, new_size);
		}
	}
}
#endif


/* returns 1 if the packet is a valid type during kex (see 7.1 of rfc4253) */
static int packet_is_okay_kex(unsigned char type) {
	if (type >= SSH_MSG_USERAUTH_REQUEST) {
		return 0;
	}
	if (type == SSH_MSG_SERVICE_REQUEST || type == SSH_MSG_SERVICE_ACCEPT) {
		return 0;
	}
	if (type == SSH_MSG_KEXINIT) {
		/* XXX should this die horribly if !dataallowed ?? */
		return 0;
	}
	return 1;
}

static void enqueue_reply_packet() {
	struct packetlist * new_item = NULL;
	new_item = m_malloc(sizeof(struct packetlist));
	new_item->next = NULL;
	
	new_item->payload = buf_newcopy(ses.writepayload);
	buf_setpos(ses.writepayload, 0);
	buf_setlen(ses.writepayload, 0);
	
	if (ses.reply_queue_tail) {
		ses.reply_queue_tail->next = new_item;
	} else {
		ses.reply_queue_head = new_item;
	}
	ses.reply_queue_tail = new_item;
}

void maybe_flush_reply_queue() {
	struct packetlist *tmp_item = NULL, *curr_item = NULL;
	if (!ses.dataallowed)
	{
		TRACE(("maybe_empty_reply_queue - no data allowed"))
		return;
	}
		
	for (curr_item = ses.reply_queue_head; curr_item; ) {
		CHECKCLEARTOWRITE();
		buf_putbytes(ses.writepayload,
			curr_item->payload->data, curr_item->payload->len);
			
		buf_free(curr_item->payload);
		tmp_item = curr_item;
		curr_item = curr_item->next;
		m_free(tmp_item);
		encrypt_packet();
	}
	ses.reply_queue_head = ses.reply_queue_tail = NULL;
}
	
/* encrypt the writepayload, putting into writebuf, ready for write_packet()
 * to put on the wire */
void encrypt_packet() {

	unsigned char padlen;
	unsigned char blocksize, mac_size;
	buffer * writebuf; /* the packet which will go on the wire. This is 
	                      encrypted in-place. */
	unsigned char packet_type;
	unsigned int len, encrypt_buf_size;
	unsigned char mac_bytes[MAX_MAC_LEN];

	time_t now;
	
	TRACE2(("enter encrypt_packet()"))

	buf_setpos(ses.writepayload, 0);
	packet_type = buf_getbyte(ses.writepayload);
	buf_setpos(ses.writepayload, 0);

	TRACE2(("encrypt_packet type is %d", packet_type))
	
	if ((!ses.dataallowed && !packet_is_okay_kex(packet_type))) {
		/* During key exchange only particular packets are allowed.
			Since this packet_type isn't OK we just enqueue it to send 
			after the KEX, see maybe_flush_reply_queue */
		enqueue_reply_packet();
		return;
	}
		
	blocksize = ses.keys->trans.algo_crypt->blocksize;
	mac_size = ses.keys->trans.algo_mac->hashsize;

	/* Encrypted packet len is payload+5. We need to then make sure
	 * there is enough space for padding or MIN_PACKET_LEN. 
	 * Add extra 3 since we need at least 4 bytes of padding */
	encrypt_buf_size = (ses.writepayload->len+4+1) 
		+ MAX(MIN_PACKET_LEN, blocksize) + 3
	/* add space for the MAC at the end */
				+ mac_size
#ifndef DISABLE_ZLIB
	/* some extra in case 'compression' makes it larger */
				+ ZLIB_COMPRESS_EXPANSION
#endif
	/* and an extra cleartext (stripped before transmission) byte for the
	 * packet type */
				+ 1;

	writebuf = buf_new(encrypt_buf_size);
	buf_setlen(writebuf, PACKET_PAYLOAD_OFF);
	buf_setpos(writebuf, PACKET_PAYLOAD_OFF);

#ifndef DISABLE_ZLIB
	/* compression */
	if (is_compress_trans()) {
		buf_compress(writebuf, ses.writepayload, ses.writepayload->len);
	} else
#endif
	{
		memcpy(buf_getwriteptr(writebuf, ses.writepayload->len),
				buf_getptr(ses.writepayload, ses.writepayload->len),
				ses.writepayload->len);
		buf_incrwritepos(writebuf, ses.writepayload->len);
	}

	/* finished with payload */
	buf_setpos(ses.writepayload, 0);
	buf_setlen(ses.writepayload, 0);

	/* length of padding - packet length must be a multiple of blocksize,
	 * with a minimum of 4 bytes of padding */
	padlen = blocksize - (writebuf->len) % blocksize;
	if (padlen < 4) {
		padlen += blocksize;
	}
	/* check for min packet length */
	if (writebuf->len + padlen < MIN_PACKET_LEN) {
		padlen += blocksize;
	}

	buf_setpos(writebuf, 0);
	/* packet length excluding the packetlength uint32 */
	buf_putint(writebuf, writebuf->len + padlen - 4);

	/* padding len */
	buf_putbyte(writebuf, padlen);
	/* actual padding */
	buf_setpos(writebuf, writebuf->len);
	buf_incrlen(writebuf, padlen);
	genrandom(buf_getptr(writebuf, padlen), padlen);

	make_mac(ses.transseq, &ses.keys->trans, writebuf, writebuf->len, mac_bytes);

	/* do the actual encryption, in-place */
	buf_setpos(writebuf, 0);
	/* encrypt it in-place*/
	len = writebuf->len;
	if (ses.keys->trans.crypt_mode->encrypt(
				buf_getptr(writebuf, len),
				buf_getwriteptr(writebuf, len),
				len,
				&ses.keys->trans.cipher_state) != CRYPT_OK) {
		dropbear_exit("Error encrypting");
	}
	buf_incrpos(writebuf, len);

    /* stick the MAC on it */
    buf_putbytes(writebuf, mac_bytes, mac_size);

	/* The last byte of the buffer stores the cleartext packet_type. It is not
	 * transmitted but is used for transmit timeout purposes */
	buf_putbyte(writebuf, packet_type);
	/* enqueue the packet for sending. It will get freed after transmission. */
	buf_setpos(writebuf, 0);
	enqueue(&ses.writequeue, (void*)writebuf);

	/* Update counts */
	ses.kexstate.datatrans += writebuf->len;
	ses.transseq++;

	now = monotonic_now();
	ses.last_packet_time_any_sent = now;
	/* idle timeout shouldn't be affected by responses to keepalives.
	send_msg_keepalive() itself also does tricks with 
	ses.last_packet_idle_time - read that if modifying this code */
	if (packet_type != SSH_MSG_REQUEST_FAILURE
		&& packet_type != SSH_MSG_UNIMPLEMENTED
		&& packet_type != SSH_MSG_IGNORE) {
		ses.last_packet_time_idle = now;

	}

	TRACE2(("leave encrypt_packet()"))
}


/* Create the packet mac, and append H(seqno|clearbuf) to the output */
/* output_mac must have ses.keys->trans.algo_mac->hashsize bytes. */
static void make_mac(unsigned int seqno, const struct key_context_directional * key_state,
		buffer * clear_buf, unsigned int clear_len, 
		unsigned char *output_mac) {
	unsigned char seqbuf[4];
	unsigned long bufsize;
	hmac_state hmac;

	if (key_state->algo_mac->hashsize > 0) {
		/* calculate the mac */
		if (hmac_init(&hmac, 
					key_state->hash_index,
					key_state->mackey,
					key_state->algo_mac->keysize) != CRYPT_OK) {
			dropbear_exit("HMAC error");
		}
	
		/* sequence number */
		STORE32H(seqno, seqbuf);
		if (hmac_process(&hmac, seqbuf, 4) != CRYPT_OK) {
			dropbear_exit("HMAC error");
		}
	
		/* the actual contents */
		buf_setpos(clear_buf, 0);
		if (hmac_process(&hmac, 
					buf_getptr(clear_buf, clear_len),
					clear_len) != CRYPT_OK) {
			dropbear_exit("HMAC error");
		}
	
        bufsize = MAX_MAC_LEN;
		if (hmac_done(&hmac, output_mac, &bufsize) != CRYPT_OK) {
			dropbear_exit("HMAC error");
		}
	}
	TRACE2(("leave writemac"))
}

#ifndef DISABLE_ZLIB
/* compresses len bytes from src, outputting to dest (starting from the
 * respective current positions. */
static void buf_compress(buffer * dest, buffer * src, unsigned int len) {

	unsigned int endpos = src->pos + len;
	int result;

	TRACE2(("enter buf_compress"))

	while (1) {

		ses.keys->trans.zstream->avail_in = endpos - src->pos;
		ses.keys->trans.zstream->next_in = 
			buf_getptr(src, ses.keys->trans.zstream->avail_in);

		ses.keys->trans.zstream->avail_out = dest->size - dest->pos;
		ses.keys->trans.zstream->next_out =
			buf_getwriteptr(dest, ses.keys->trans.zstream->avail_out);

		result = deflate(ses.keys->trans.zstream, Z_SYNC_FLUSH);

		buf_setpos(src, endpos - ses.keys->trans.zstream->avail_in);
		buf_setlen(dest, dest->size - ses.keys->trans.zstream->avail_out);
		buf_setpos(dest, dest->len);

		if (result != Z_OK) {
			dropbear_exit("zlib error");
		}

		if (ses.keys->trans.zstream->avail_in == 0) {
			break;
		}

		dropbear_assert(ses.keys->trans.zstream->avail_out == 0);

		/* the buffer has been filled, we must extend. This only happens in
		 * unusual circumstances where the data grows in size after deflate(),
		 * but it is possible */
		buf_resize(dest, dest->size + ZLIB_COMPRESS_EXPANSION);

	}
	TRACE2(("leave buf_compress"))
}
#endif
