11305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* $OpenBSD: roaming_client.c,v 1.3 2010/01/18 01:50:27 dtucker Exp $ */
21305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/*
31305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Copyright (c) 2004-2009 AppGate Network Security AB
41305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *
51305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Permission to use, copy, modify, and distribute this software for any
61305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * purpose with or without fee is hereby granted, provided that the above
71305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * copyright notice and this permission notice appear in all copies.
81305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *
91305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood */
171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "includes.h"
191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "openbsd-compat/sys-queue.h"
211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <sys/types.h>
221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <sys/socket.h>
231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifdef HAVE_INTTYPES_H
251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <inttypes.h>
261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif
271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <signal.h>
281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <string.h>
291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <unistd.h>
301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <openssl/crypto.h>
321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <openssl/sha.h>
331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "xmalloc.h"
351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "buffer.h"
361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "channels.h"
371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "cipher.h"
381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "dispatch.h"
391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "clientloop.h"
401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "log.h"
411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "match.h"
421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "misc.h"
431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "packet.h"
441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "ssh.h"
451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "key.h"
461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "kex.h"
471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "readconf.h"
481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "roaming.h"
491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "ssh2.h"
501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "sshconnect.h"
511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* import */
531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodextern Options options;
541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodextern char *host;
551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodextern struct sockaddr_storage hostaddr;
561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodextern int session_resumed;
571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic u_int32_t roaming_id;
591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic u_int64_t cookie;
601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic u_int64_t lastseenchall;
611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic u_int64_t key1, key2, oldkey1, oldkey2;
621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodvoid
641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodroaming_reply(int type, u_int32_t seq, void *ctxt)
651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (type == SSH2_MSG_REQUEST_FAILURE) {
671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		logit("Server denied roaming");
681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return;
691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	verbose("Roaming enabled");
711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	roaming_id = packet_get_int();
721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	cookie = packet_get_int64();
731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	key1 = oldkey1 = packet_get_int64();
741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	key2 = oldkey2 = packet_get_int64();
751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	set_out_buffer_size(packet_get_int() +  get_snd_buf_size());
761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	roaming_enabled = 1;
771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodvoid
801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodrequest_roaming(void)
811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_start(SSH2_MSG_GLOBAL_REQUEST);
831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_put_cstring(ROAMING_REQUEST);
841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_put_char(1);
851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_put_int(get_recv_buf_size());
861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_send();
871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	client_register_global_confirm(roaming_reply, NULL);
881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic void
911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodroaming_auth_required(void)
921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	u_char digest[SHA_DIGEST_LENGTH];
941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	EVP_MD_CTX md;
951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	Buffer b;
961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	const EVP_MD *evp_md = EVP_sha1();
971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	u_int64_t chall, oldchall;
981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	chall = packet_get_int64();
1001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	oldchall = packet_get_int64();
1011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (oldchall != lastseenchall) {
1021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		key1 = oldkey1;
1031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		key2 = oldkey2;
1041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
1051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	lastseenchall = chall;
1061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	buffer_init(&b);
1081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	buffer_put_int64(&b, cookie);
1091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	buffer_put_int64(&b, chall);
1101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	EVP_DigestInit(&md, evp_md);
1111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	EVP_DigestUpdate(&md, buffer_ptr(&b), buffer_len(&b));
1121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	EVP_DigestFinal(&md, digest, NULL);
1131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	buffer_free(&b);
1141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_start(SSH2_MSG_KEX_ROAMING_AUTH);
1161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_put_int64(key1 ^ get_recv_bytes());
1171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_put_raw(digest, sizeof(digest));
1181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_send();
1191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	oldkey1 = key1;
1211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	oldkey2 = key2;
1221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	calculate_new_key(&key1, cookie, chall);
1231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	calculate_new_key(&key2, cookie, chall);
1241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	debug("Received %llu bytes", (unsigned long long)get_recv_bytes());
1261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	debug("Sent roaming_auth packet");
1271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
1281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodint
1301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodresume_kex(void)
1311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
1321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/*
1331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * This should not happen - if the client sends the kex method
1341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * resume@appgate.com then the kex is done in roaming_resume().
1351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 */
1361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	return 1;
1371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
1381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic int
1401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodroaming_resume(void)
1411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
1421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	u_int64_t recv_bytes;
1431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	char *str = NULL, *kexlist = NULL, *c;
1441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	int i, type;
1451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	int timeout_ms = options.connection_timeout * 1000;
1461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	u_int len;
1471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	u_int32_t rnd = 0;
1481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	resume_in_progress = 1;
1501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* Exchange banners */
1521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	ssh_exchange_identification(timeout_ms);
1531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_set_nonblocking();
1541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* Send a kexinit message with resume@appgate.com as only kex algo */
1561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_start(SSH2_MSG_KEXINIT);
1571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	for (i = 0; i < KEX_COOKIE_LEN; i++) {
1581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (i % 4 == 0)
1591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			rnd = arc4random();
1601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		packet_put_char(rnd & 0xff);
1611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		rnd >>= 8;
1621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
1631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_put_cstring(KEX_RESUME);
1641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	for (i = 1; i < PROPOSAL_MAX; i++) {
1651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		/* kex algorithm added so start with i=1 and not 0 */
1661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		packet_put_cstring(""); /* Not used when we resume */
1671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
1681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_put_char(1); /* first kex_packet follows */
1691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_put_int(0); /* reserved */
1701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_send();
1711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* Assume that resume@appgate.com will be accepted */
1731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_start(SSH2_MSG_KEX_ROAMING_RESUME);
1741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_put_int(roaming_id);
1751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_send();
1761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* Read the server's kexinit and check for resume@appgate.com */
1781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if ((type = packet_read()) != SSH2_MSG_KEXINIT) {
1791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		debug("expected kexinit on resume, got %d", type);
1801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		goto fail;
1811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
1821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	for (i = 0; i < KEX_COOKIE_LEN; i++)
1831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		(void)packet_get_char();
1841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	kexlist = packet_get_string(&len);
1851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (!kexlist
1861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    || (str = match_list(KEX_RESUME, kexlist, NULL)) == NULL) {
1871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		debug("server doesn't allow resume");
1881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		goto fail;
1891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
1901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	xfree(str);
1911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	for (i = 1; i < PROPOSAL_MAX; i++) {
1921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		/* kex algorithm taken care of so start with i=1 and not 0 */
1931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		xfree(packet_get_string(&len));
1941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
1951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	i = packet_get_char(); /* first_kex_packet_follows */
1961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (i && (c = strchr(kexlist, ',')))
1971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		*c = 0;
1981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (i && strcmp(kexlist, KEX_RESUME)) {
1991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		debug("server's kex guess (%s) was wrong, skipping", kexlist);
2001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		(void)packet_read(); /* Wrong guess - discard packet */
2011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
2021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
2031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/*
2041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * Read the ROAMING_AUTH_REQUIRED challenge from the server and
2051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * send ROAMING_AUTH
2061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 */
2071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if ((type = packet_read()) != SSH2_MSG_KEX_ROAMING_AUTH_REQUIRED) {
2081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		debug("expected roaming_auth_required, got %d", type);
2091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		goto fail;
2101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
2111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	roaming_auth_required();
2121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
2131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* Read ROAMING_AUTH_OK from the server */
2141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if ((type = packet_read()) != SSH2_MSG_KEX_ROAMING_AUTH_OK) {
2151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		debug("expected roaming_auth_ok, got %d", type);
2161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		goto fail;
2171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
2181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	recv_bytes = packet_get_int64() ^ oldkey2;
2191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	debug("Peer received %llu bytes", (unsigned long long)recv_bytes);
2201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	resend_bytes(packet_get_connection_out(), &recv_bytes);
2211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
2221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	resume_in_progress = 0;
2231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
2241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	session_resumed = 1; /* Tell clientloop */
2251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
2261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	return 0;
2271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
2281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodfail:
2291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (kexlist)
2301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		xfree(kexlist);
2311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (packet_get_connection_in() == packet_get_connection_out())
2321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		close(packet_get_connection_in());
2331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	else {
2341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		close(packet_get_connection_in());
2351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		close(packet_get_connection_out());
2361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
2371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	return 1;
2381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
2391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
2401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodint
2411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodwait_for_roaming_reconnect(void)
2421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
2431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	static int reenter_guard = 0;
2441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	int timeout_ms = options.connection_timeout * 1000;
2451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	int c;
2461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
2471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (reenter_guard != 0)
2481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		fatal("Server refused resume, roaming timeout may be exceeded");
2491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	reenter_guard = 1;
2501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
2511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	fprintf(stderr, "[connection suspended, press return to resume]");
2521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	fflush(stderr);
2531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_backup_state();
2541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* TODO Perhaps we should read from tty here */
2551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	while ((c = fgetc(stdin)) != EOF) {
2561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (c == 'Z' - 64) {
2571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			kill(getpid(), SIGTSTP);
2581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			continue;
2591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
2601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (c != '\n' && c != '\r')
2611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			continue;
2621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
2631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (ssh_connect(host, &hostaddr, options.port,
2641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    options.address_family, 1, &timeout_ms,
2651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    options.tcp_keep_alive, options.use_privileged_port,
2661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    options.proxy_command) == 0 && roaming_resume() == 0) {
2671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			packet_restore_state();
2681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			reenter_guard = 0;
2691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			fprintf(stderr, "[connection resumed]\n");
2701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			fflush(stderr);
2711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			return 0;
2721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
2731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
2741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		fprintf(stderr, "[reconnect failed, press return to retry]");
2751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		fflush(stderr);
2761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
2771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	fprintf(stderr, "[exiting]\n");
2781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	fflush(stderr);
2791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	exit(0);
2801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
281