/* $OpenBSD: roaming_client.c,v 1.4 2011/12/07 05:44:38 djm Exp $ */
/*
 * Copyright (c) 2004-2009 AppGate Network Security AB
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

#include "includes.h"

#include "openbsd-compat/sys-queue.h"
#include <sys/types.h>
#include <sys/socket.h>

#ifdef HAVE_INTTYPES_H
#include <inttypes.h>
#endif
#include <signal.h>
#include <string.h>
#include <unistd.h>

#include <openssl/crypto.h>
#include <openssl/sha.h>

#include "xmalloc.h"
#include "buffer.h"
#include "channels.h"
#include "cipher.h"
#include "dispatch.h"
#include "clientloop.h"
#include "log.h"
#include "match.h"
#include "misc.h"
#include "packet.h"
#include "ssh.h"
#include "key.h"
#include "kex.h"
#include "readconf.h"
#include "roaming.h"
#include "ssh2.h"
#include "sshconnect.h"

/* import */
extern Options options;
extern char *host;
extern struct sockaddr_storage hostaddr;
extern int session_resumed;

static u_int32_t roaming_id;
static u_int64_t cookie;
static u_int64_t lastseenchall;
static u_int64_t key1, key2, oldkey1, oldkey2;

void
roaming_reply(int type, u_int32_t seq, void *ctxt)
{
	if (type == SSH2_MSG_REQUEST_FAILURE) {
		logit("Server denied roaming");
		return;
	}
	verbose("Roaming enabled");
	roaming_id = packet_get_int();
	cookie = packet_get_int64();
	key1 = oldkey1 = packet_get_int64();
	key2 = oldkey2 = packet_get_int64();
	set_out_buffer_size(packet_get_int() + get_snd_buf_size());
	roaming_enabled = 1;
}

void
request_roaming(void)
{
	packet_start(SSH2_MSG_GLOBAL_REQUEST);
	packet_put_cstring(ROAMING_REQUEST);
	packet_put_char(1);
	packet_put_int(get_recv_buf_size());
	packet_send();
	client_register_global_confirm(roaming_reply, NULL);
}

static void
roaming_auth_required(void)
{
	u_char digest[SHA_DIGEST_LENGTH];
	EVP_MD_CTX md;
	Buffer b;
	const EVP_MD *evp_md = EVP_sha1();
	u_int64_t chall, oldchall;

	chall = packet_get_int64();
	oldchall = packet_get_int64();
	if (oldchall != lastseenchall) {
		key1 = oldkey1;
		key2 = oldkey2;
	}
	lastseenchall = chall;

	buffer_init(&b);
	buffer_put_int64(&b, cookie);
	buffer_put_int64(&b, chall);
	EVP_DigestInit(&md, evp_md);
	EVP_DigestUpdate(&md, buffer_ptr(&b), buffer_len(&b));
	EVP_DigestFinal(&md, digest, NULL);
	buffer_free(&b);

	packet_start(SSH2_MSG_KEX_ROAMING_AUTH);
	packet_put_int64(key1 ^ get_recv_bytes());
	packet_put_raw(digest, sizeof(digest));
	packet_send();

	oldkey1 = key1;
	oldkey2 = key2;
	calculate_new_key(&key1, cookie, chall);
	calculate_new_key(&key2, cookie, chall);

	debug("Received %llu bytes", (unsigned long long)get_recv_bytes());
	debug("Sent roaming_auth packet");
}

int
resume_kex(void)
{
	/*
	 * This should not happen - if the client sends the kex method
	 * resume@appgate.com then the kex is done in roaming_resume().
	 */
	return 1;
}

static int
roaming_resume(void)
{
	u_int64_t recv_bytes;
	char *str = NULL, *kexlist = NULL, *c;
	int i, type;
	int timeout_ms = options.connection_timeout * 1000;
	u_int len;
	u_int32_t rnd = 0;

	resume_in_progress = 1;

	/* Exchange banners */
	ssh_exchange_identification(timeout_ms);
	packet_set_nonblocking();

	/* Send a kexinit message with resume@appgate.com as only kex algo */
	packet_start(SSH2_MSG_KEXINIT);
	for (i = 0; i < KEX_COOKIE_LEN; i++) {
		if (i % 4 == 0)
			rnd = arc4random();
		packet_put_char(rnd & 0xff);
		rnd >>= 8;
	}
	packet_put_cstring(KEX_RESUME);
	for (i = 1; i < PROPOSAL_MAX; i++) {
		/* kex algorithm added so start with i=1 and not 0 */
		packet_put_cstring(""); /* Not used when we resume */
	}
	packet_put_char(1); /* first kex_packet follows */
	packet_put_int(0); /* reserved */
	packet_send();

	/* Assume that resume@appgate.com will be accepted */
	packet_start(SSH2_MSG_KEX_ROAMING_RESUME);
	packet_put_int(roaming_id);
	packet_send();

	/* Read the server's kexinit and check for resume@appgate.com */
	if ((type = packet_read()) != SSH2_MSG_KEXINIT) {
		debug("expected kexinit on resume, got %d", type);
		goto fail;
	}
	for (i = 0; i < KEX_COOKIE_LEN; i++)
		(void)packet_get_char();
	kexlist = packet_get_string(&len);
	if (!kexlist
	    || (str = match_list(KEX_RESUME, kexlist, NULL)) == NULL) {
		debug("server doesn't allow resume");
		goto fail;
	}
	xfree(str);
	for (i = 1; i < PROPOSAL_MAX; i++) {
		/* kex algorithm taken care of so start with i=1 and not 0 */
		xfree(packet_get_string(&len));
	}
	i = packet_get_char(); /* first_kex_packet_follows */
	if (i && (c = strchr(kexlist, ',')))
		*c = 0;
	if (i && strcmp(kexlist, KEX_RESUME)) {
		debug("server's kex guess (%s) was wrong, skipping", kexlist);
		(void)packet_read(); /* Wrong guess - discard packet */
	}

	/*
	 * Read the ROAMING_AUTH_REQUIRED challenge from the server and
	 * send ROAMING_AUTH
	 */
	if ((type = packet_read()) != SSH2_MSG_KEX_ROAMING_AUTH_REQUIRED) {
		debug("expected roaming_auth_required, got %d", type);
		goto fail;
	}
	roaming_auth_required();

	/* Read ROAMING_AUTH_OK from the server */
	if ((type = packet_read()) != SSH2_MSG_KEX_ROAMING_AUTH_OK) {
		debug("expected roaming_auth_ok, got %d", type);
		goto fail;
	}
	recv_bytes = packet_get_int64() ^ oldkey2;
	debug("Peer received %llu bytes", (unsigned long long)recv_bytes);
	resend_bytes(packet_get_connection_out(), &recv_bytes);

	resume_in_progress = 0;

	session_resumed = 1; /* Tell clientloop */

	return 0;

fail:
	if (kexlist)
		xfree(kexlist);
	if (packet_get_connection_in() == packet_get_connection_out())
		close(packet_get_connection_in());
	else {
		close(packet_get_connection_in());
		close(packet_get_connection_out());
	}
	return 1;
}

int
wait_for_roaming_reconnect(void)
{
	static int reenter_guard = 0;
	int timeout_ms = options.connection_timeout * 1000;
	int c;

	if (reenter_guard != 0)
		fatal("Server refused resume, roaming timeout may be exceeded");
	reenter_guard = 1;

	fprintf(stderr, "[connection suspended, press return to resume]");
	fflush(stderr);
	packet_backup_state();
	/* TODO Perhaps we should read from tty here */
	while ((c = fgetc(stdin)) != EOF) {
		if (c == 'Z' - 64) {
			kill(getpid(), SIGTSTP);
			continue;
		}
		if (c != '\n' && c != '\r')
			continue;

		if (ssh_connect(host, &hostaddr, options.port,
		    options.address_family, 1, &timeout_ms,
		    options.tcp_keep_alive, options.use_privileged_port,
		    options.proxy_command) == 0 && roaming_resume() == 0) {
			packet_restore_state();
			reenter_guard = 0;
			fprintf(stderr, "[connection resumed]\n");
			fflush(stderr);
			return 0;
		}

		fprintf(stderr, "[reconnect failed, press return to retry]");
		fflush(stderr);
	}
	fprintf(stderr, "[exiting]\n");
	fflush(stderr);
	exit(0);
}
