11305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* $OpenBSD: sshconnect2.c,v 1.188 2011/05/24 07:15:47 djm Exp $ */
21305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/*
31305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Copyright (c) 2000 Markus Friedl.  All rights reserved.
41305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Copyright (c) 2008 Damien Miller.  All rights reserved.
51305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *
61305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Redistribution and use in source and binary forms, with or without
71305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * modification, are permitted provided that the following conditions
81305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * are met:
91305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * 1. Redistributions of source code must retain the above copyright
101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *    notice, this list of conditions and the following disclaimer.
111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * 2. Redistributions in binary form must reproduce the above copyright
121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *    notice, this list of conditions and the following disclaimer in the
131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *    documentation and/or other materials provided with the distribution.
141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *
151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood */
261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "includes.h"
281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <sys/types.h>
301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <sys/socket.h>
311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <sys/wait.h>
321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <sys/stat.h>
331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <errno.h>
351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <fcntl.h>
361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <netdb.h>
371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <pwd.h>
381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <signal.h>
391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <stdarg.h>
401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <stdio.h>
411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <string.h>
421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <unistd.h>
431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#if defined(HAVE_STRNVIS) && defined(HAVE_VIS_H)
441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <vis.h>
451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif
461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "openbsd-compat/sys-queue.h"
481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "xmalloc.h"
501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "ssh.h"
511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "ssh2.h"
521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "buffer.h"
531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "packet.h"
541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "compat.h"
551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "cipher.h"
561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "key.h"
571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "kex.h"
581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "myproposal.h"
591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "sshconnect.h"
601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "authfile.h"
611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "dh.h"
621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "authfd.h"
631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "log.h"
641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "readconf.h"
651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "misc.h"
661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "match.h"
671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "dispatch.h"
681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "canohost.h"
691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "msg.h"
701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "pathnames.h"
711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "uidswap.h"
721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "hostfile.h"
731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "schnorr.h"
741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "jpake.h"
751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifdef GSSAPI
771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "ssh-gss.h"
781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif
791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* import */
811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodextern char *client_version_string;
821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodextern char *server_version_string;
831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodextern Options options;
841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/*
861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * SSH2 key exchange
871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood */
881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodu_char *session_id2 = NULL;
901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodu_int session_id2_len = 0;
911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodchar *xxx_host;
931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstruct sockaddr *xxx_hostaddr;
941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
951305e95ba6ff9fa202d0818caf10405df4b0f648Mike LockwoodKex *xxx_kex = NULL;
961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic int
981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodverify_host_key_callback(Key *hostkey)
991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
1001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (verify_host_key(xxx_host, xxx_hostaddr, hostkey) == -1)
1011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		fatal("Host key verification failed.");
1021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	return 0;
1031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
1041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic char *
1061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodorder_hostkeyalgs(char *host, struct sockaddr *hostaddr, u_short port)
1071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
1081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	char *oavail, *avail, *first, *last, *alg, *hostname, *ret;
1091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	size_t maxlen;
1101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	struct hostkeys *hostkeys;
1111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	int ktype;
1121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	u_int i;
1131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* Find all hostkeys for this hostname */
1151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	get_hostfile_hostname_ipaddr(host, hostaddr, port, &hostname, NULL);
1161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	hostkeys = init_hostkeys();
1171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	for (i = 0; i < options.num_user_hostfiles; i++)
1181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		load_hostkeys(hostkeys, hostname, options.user_hostfiles[i]);
1191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	for (i = 0; i < options.num_system_hostfiles; i++)
1201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		load_hostkeys(hostkeys, hostname, options.system_hostfiles[i]);
1211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	oavail = avail = xstrdup(KEX_DEFAULT_PK_ALG);
1231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	maxlen = strlen(avail) + 1;
1241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	first = xmalloc(maxlen);
1251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	last = xmalloc(maxlen);
1261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	*first = *last = '\0';
1271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#define ALG_APPEND(to, from) \
1291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	do { \
1301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (*to != '\0') \
1311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			strlcat(to, ",", maxlen); \
1321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		strlcat(to, from, maxlen); \
1331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	} while (0)
1341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	while ((alg = strsep(&avail, ",")) && *alg != '\0') {
1361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if ((ktype = key_type_from_name(alg)) == KEY_UNSPEC)
1371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			fatal("%s: unknown alg %s", __func__, alg);
1381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (lookup_key_in_hostkeys_by_type(hostkeys,
1391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    key_type_plain(ktype), NULL))
1401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			ALG_APPEND(first, alg);
1411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		else
1421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			ALG_APPEND(last, alg);
1431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
1441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#undef ALG_APPEND
1451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	xasprintf(&ret, "%s%s%s", first, *first == '\0' ? "" : ",", last);
1461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (*first != '\0')
1471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		debug3("%s: prefer hostkeyalgs: %s", __func__, first);
1481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	xfree(first);
1501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	xfree(last);
1511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	xfree(hostname);
1521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	xfree(oavail);
1531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	free_hostkeys(hostkeys);
1541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	return ret;
1561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
1571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodvoid
1591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodssh_kex2(char *host, struct sockaddr *hostaddr, u_short port)
1601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
1611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	Kex *kex;
1621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	xxx_host = host;
1641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	xxx_hostaddr = hostaddr;
1651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (options.ciphers == (char *)-1) {
1671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		logit("No valid ciphers for protocol version 2 given, using defaults.");
1681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		options.ciphers = NULL;
1691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
1701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (options.ciphers != NULL) {
1711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		myproposal[PROPOSAL_ENC_ALGS_CTOS] =
1721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		myproposal[PROPOSAL_ENC_ALGS_STOC] = options.ciphers;
1731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
1741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	myproposal[PROPOSAL_ENC_ALGS_CTOS] =
1751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    compat_cipher_proposal(myproposal[PROPOSAL_ENC_ALGS_CTOS]);
1761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	myproposal[PROPOSAL_ENC_ALGS_STOC] =
1771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    compat_cipher_proposal(myproposal[PROPOSAL_ENC_ALGS_STOC]);
1781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (options.compression) {
1791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		myproposal[PROPOSAL_COMP_ALGS_CTOS] =
1801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		myproposal[PROPOSAL_COMP_ALGS_STOC] = "zlib@openssh.com,zlib,none";
1811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	} else {
1821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		myproposal[PROPOSAL_COMP_ALGS_CTOS] =
1831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		myproposal[PROPOSAL_COMP_ALGS_STOC] = "none,zlib@openssh.com,zlib";
1841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
1851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (options.macs != NULL) {
1861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		myproposal[PROPOSAL_MAC_ALGS_CTOS] =
1871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		myproposal[PROPOSAL_MAC_ALGS_STOC] = options.macs;
1881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
1891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (options.hostkeyalgorithms != NULL)
1901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] =
1911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    options.hostkeyalgorithms;
1921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	else {
1931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		/* Prefer algorithms that we already have keys for */
1941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] =
1951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    order_hostkeyalgs(host, hostaddr, port);
1961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
1971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (options.kex_algorithms != NULL)
1981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		myproposal[PROPOSAL_KEX_ALGS] = options.kex_algorithms;
1991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
2001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (options.rekey_limit)
2011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		packet_set_rekey_limit((u_int32_t)options.rekey_limit);
2021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
2031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* start key exchange */
2041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	kex = kex_setup(myproposal);
2051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	kex->kex[KEX_DH_GRP1_SHA1] = kexdh_client;
2061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	kex->kex[KEX_DH_GRP14_SHA1] = kexdh_client;
2071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	kex->kex[KEX_DH_GEX_SHA1] = kexgex_client;
2081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	kex->kex[KEX_DH_GEX_SHA256] = kexgex_client;
2091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	kex->kex[KEX_ECDH_SHA2] = kexecdh_client;
2101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	kex->client_version_string=client_version_string;
2111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	kex->server_version_string=server_version_string;
2121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	kex->verify_host_key=&verify_host_key_callback;
2131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
2141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	xxx_kex = kex;
2151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
2161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	dispatch_run(DISPATCH_BLOCK, &kex->done, kex);
2171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
2181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (options.use_roaming && !kex->roaming) {
2191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		debug("Roaming not allowed by server");
2201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		options.use_roaming = 0;
2211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
2221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
2231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	session_id2 = kex->session_id;
2241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	session_id2_len = kex->session_id_len;
2251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
2261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifdef DEBUG_KEXDH
2271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* send 1st encrypted/maced/compressed message */
2281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_start(SSH2_MSG_IGNORE);
2291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_put_cstring("markus");
2301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_send();
2311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_write_wait();
2321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif
2331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
2341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
2351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/*
2361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Authenticate user
2371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood */
2381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
2391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodtypedef struct Authctxt Authctxt;
2401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodtypedef struct Authmethod Authmethod;
2411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodtypedef struct identity Identity;
2421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodtypedef struct idlist Idlist;
2431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
2441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstruct identity {
2451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	TAILQ_ENTRY(identity) next;
2461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	AuthenticationConnection *ac;	/* set if agent supports key */
2471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	Key	*key;			/* public/private key */
2481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	char	*filename;		/* comment for agent-only keys */
2491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	int	tried;
2501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	int	isprivate;		/* key points to the private key */
2511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood};
2521305e95ba6ff9fa202d0818caf10405df4b0f648Mike LockwoodTAILQ_HEAD(idlist, identity);
2531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
2541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstruct Authctxt {
2551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	const char *server_user;
2561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	const char *local_user;
2571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	const char *host;
2581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	const char *service;
2591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	Authmethod *method;
2601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	sig_atomic_t success;
2611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	char *authlist;
2621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* pubkey */
2631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	Idlist keys;
2641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	AuthenticationConnection *agent;
2651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* hostbased */
2661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	Sensitive *sensitive;
2671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* kbd-interactive */
2681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	int info_req_seen;
2691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* generic */
2701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	void *methoddata;
2711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood};
2721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstruct Authmethod {
2731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	char	*name;		/* string to compare against server's list */
2741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	int	(*userauth)(Authctxt *authctxt);
2751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	void	(*cleanup)(Authctxt *authctxt);
2761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	int	*enabled;	/* flag in option struct that enables method */
2771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	int	*batch_flag;	/* flag in option struct that disables method */
2781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood};
2791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
2801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodvoid	input_userauth_success(int, u_int32_t, void *);
2811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodvoid	input_userauth_success_unexpected(int, u_int32_t, void *);
2821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodvoid	input_userauth_failure(int, u_int32_t, void *);
2831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodvoid	input_userauth_banner(int, u_int32_t, void *);
2841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodvoid	input_userauth_error(int, u_int32_t, void *);
2851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodvoid	input_userauth_info_req(int, u_int32_t, void *);
2861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodvoid	input_userauth_pk_ok(int, u_int32_t, void *);
2871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodvoid	input_userauth_passwd_changereq(int, u_int32_t, void *);
2881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodvoid	input_userauth_jpake_server_step1(int, u_int32_t, void *);
2891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodvoid	input_userauth_jpake_server_step2(int, u_int32_t, void *);
2901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodvoid	input_userauth_jpake_server_confirm(int, u_int32_t, void *);
2911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
2921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodint	userauth_none(Authctxt *);
2931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodint	userauth_pubkey(Authctxt *);
2941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodint	userauth_passwd(Authctxt *);
2951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodint	userauth_kbdint(Authctxt *);
2961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodint	userauth_hostbased(Authctxt *);
2971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodint	userauth_jpake(Authctxt *);
2981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
2991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodvoid	userauth_jpake_cleanup(Authctxt *);
3001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
3011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifdef GSSAPI
3021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodint	userauth_gssapi(Authctxt *authctxt);
3031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodvoid	input_gssapi_response(int type, u_int32_t, void *);
3041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodvoid	input_gssapi_token(int type, u_int32_t, void *);
3051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodvoid	input_gssapi_hash(int type, u_int32_t, void *);
3061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodvoid	input_gssapi_error(int, u_int32_t, void *);
3071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodvoid	input_gssapi_errtok(int, u_int32_t, void *);
3081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif
3091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
3101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodvoid	userauth(Authctxt *, char *);
3111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
3121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic int sign_and_send_pubkey(Authctxt *, Identity *);
3131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic void pubkey_prepare(Authctxt *);
3141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic void pubkey_cleanup(Authctxt *);
3151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic Key *load_identity_file(char *);
3161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
3171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic Authmethod *authmethod_get(char *authlist);
3181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic Authmethod *authmethod_lookup(const char *name);
3191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic char *authmethods_get(void);
3201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
3211305e95ba6ff9fa202d0818caf10405df4b0f648Mike LockwoodAuthmethod authmethods[] = {
3221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifdef GSSAPI
3231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	{"gssapi-with-mic",
3241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		userauth_gssapi,
3251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		NULL,
3261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		&options.gss_authentication,
3271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		NULL},
3281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif
3291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	{"hostbased",
3301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		userauth_hostbased,
3311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		NULL,
3321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		&options.hostbased_authentication,
3331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		NULL},
3341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	{"publickey",
3351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		userauth_pubkey,
3361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		NULL,
3371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		&options.pubkey_authentication,
3381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		NULL},
3391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifdef JPAKE
3401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	{"jpake-01@openssh.com",
3411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		userauth_jpake,
3421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		userauth_jpake_cleanup,
3431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		&options.zero_knowledge_password_authentication,
3441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		&options.batch_mode},
3451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif
3461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	{"keyboard-interactive",
3471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		userauth_kbdint,
3481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		NULL,
3491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		&options.kbd_interactive_authentication,
3501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		&options.batch_mode},
3511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	{"password",
3521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		userauth_passwd,
3531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		NULL,
3541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		&options.password_authentication,
3551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		&options.batch_mode},
3561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	{"none",
3571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		userauth_none,
3581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		NULL,
3591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		NULL,
3601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		NULL},
3611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	{NULL, NULL, NULL, NULL, NULL}
3621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood};
3631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
3641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodvoid
3651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodssh_userauth2(const char *local_user, const char *server_user, char *host,
3661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood    Sensitive *sensitive)
3671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
3681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	Authctxt authctxt;
3691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	int type;
3701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
3711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (options.challenge_response_authentication)
3721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		options.kbd_interactive_authentication = 1;
3731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
3741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_start(SSH2_MSG_SERVICE_REQUEST);
3751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_put_cstring("ssh-userauth");
3761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_send();
3771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	debug("SSH2_MSG_SERVICE_REQUEST sent");
3781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_write_wait();
3791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	type = packet_read();
3801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (type != SSH2_MSG_SERVICE_ACCEPT)
3811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		fatal("Server denied authentication request: %d", type);
3821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (packet_remaining() > 0) {
3831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		char *reply = packet_get_string(NULL);
3841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		debug2("service_accept: %s", reply);
3851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		xfree(reply);
3861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	} else {
3871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		debug2("buggy server: service_accept w/o service");
3881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
3891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_check_eom();
3901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	debug("SSH2_MSG_SERVICE_ACCEPT received");
3911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
3921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (options.preferred_authentications == NULL)
3931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		options.preferred_authentications = authmethods_get();
3941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
3951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* setup authentication context */
3961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	memset(&authctxt, 0, sizeof(authctxt));
3971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	pubkey_prepare(&authctxt);
3981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	authctxt.server_user = server_user;
3991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	authctxt.local_user = local_user;
4001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	authctxt.host = host;
4011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	authctxt.service = "ssh-connection";		/* service name */
4021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	authctxt.success = 0;
4031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	authctxt.method = authmethod_lookup("none");
4041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	authctxt.authlist = NULL;
4051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	authctxt.methoddata = NULL;
4061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	authctxt.sensitive = sensitive;
4071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	authctxt.info_req_seen = 0;
4081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (authctxt.method == NULL)
4091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		fatal("ssh_userauth2: internal error: cannot send userauth none request");
4101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
4111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* initial userauth request */
4121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	userauth_none(&authctxt);
4131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
4141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	dispatch_init(&input_userauth_error);
4151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	dispatch_set(SSH2_MSG_USERAUTH_SUCCESS, &input_userauth_success);
4161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	dispatch_set(SSH2_MSG_USERAUTH_FAILURE, &input_userauth_failure);
4171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	dispatch_set(SSH2_MSG_USERAUTH_BANNER, &input_userauth_banner);
4181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	dispatch_run(DISPATCH_BLOCK, &authctxt.success, &authctxt);	/* loop until success */
4191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
4201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	pubkey_cleanup(&authctxt);
4211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	dispatch_range(SSH2_MSG_USERAUTH_MIN, SSH2_MSG_USERAUTH_MAX, NULL);
4221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
4231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	debug("Authentication succeeded (%s).", authctxt.method->name);
4241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
4251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
4261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodvoid
4271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwooduserauth(Authctxt *authctxt, char *authlist)
4281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
4291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (authctxt->method != NULL && authctxt->method->cleanup != NULL)
4301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		authctxt->method->cleanup(authctxt);
4311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
4321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (authctxt->methoddata) {
4331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		xfree(authctxt->methoddata);
4341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		authctxt->methoddata = NULL;
4351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
4361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (authlist == NULL) {
4371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		authlist = authctxt->authlist;
4381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	} else {
4391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (authctxt->authlist)
4401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			xfree(authctxt->authlist);
4411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		authctxt->authlist = authlist;
4421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
4431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	for (;;) {
4441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		Authmethod *method = authmethod_get(authlist);
4451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (method == NULL)
4461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			fatal("Permission denied (%s).", authlist);
4471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		authctxt->method = method;
4481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
4491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		/* reset the per method handler */
4501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		dispatch_range(SSH2_MSG_USERAUTH_PER_METHOD_MIN,
4511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    SSH2_MSG_USERAUTH_PER_METHOD_MAX, NULL);
4521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
4531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		/* and try new method */
4541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (method->userauth(authctxt) != 0) {
4551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			debug2("we sent a %s packet, wait for reply", method->name);
4561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			break;
4571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		} else {
4581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			debug2("we did not send a packet, disable method");
4591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			method->enabled = NULL;
4601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
4611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
4621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
4631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
4641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* ARGSUSED */
4651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodvoid
4661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodinput_userauth_error(int type, u_int32_t seq, void *ctxt)
4671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
4681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	fatal("input_userauth_error: bad message during authentication: "
4691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    "type %d", type);
4701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
4711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
4721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* ARGSUSED */
4731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodvoid
4741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodinput_userauth_banner(int type, u_int32_t seq, void *ctxt)
4751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
4761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	char *msg, *raw, *lang;
4771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	u_int len;
4781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
4791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	debug3("input_userauth_banner");
4801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	raw = packet_get_string(&len);
4811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	lang = packet_get_string(NULL);
4821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (len > 0 && options.log_level >= SYSLOG_LEVEL_INFO) {
4831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (len > 65536)
4841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			len = 65536;
4851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		msg = xmalloc(len * 4 + 1); /* max expansion from strnvis() */
4861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		strnvis(msg, raw, len * 4 + 1, VIS_SAFE|VIS_OCTAL|VIS_NOSLASH);
4871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		fprintf(stderr, "%s", msg);
4881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		xfree(msg);
4891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
4901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	xfree(raw);
4911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	xfree(lang);
4921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
4931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
4941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* ARGSUSED */
4951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodvoid
4961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodinput_userauth_success(int type, u_int32_t seq, void *ctxt)
4971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
4981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	Authctxt *authctxt = ctxt;
4991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
5001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (authctxt == NULL)
5011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		fatal("input_userauth_success: no authentication context");
5021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (authctxt->authlist) {
5031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		xfree(authctxt->authlist);
5041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		authctxt->authlist = NULL;
5051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
5061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (authctxt->method != NULL && authctxt->method->cleanup != NULL)
5071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		authctxt->method->cleanup(authctxt);
5081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (authctxt->methoddata) {
5091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		xfree(authctxt->methoddata);
5101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		authctxt->methoddata = NULL;
5111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
5121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	authctxt->success = 1;			/* break out */
5131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
5141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
5151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodvoid
5161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodinput_userauth_success_unexpected(int type, u_int32_t seq, void *ctxt)
5171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
5181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	Authctxt *authctxt = ctxt;
5191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
5201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (authctxt == NULL)
5211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		fatal("%s: no authentication context", __func__);
5221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
5231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	fatal("Unexpected authentication success during %s.",
5241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    authctxt->method->name);
5251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
5261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
5271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* ARGSUSED */
5281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodvoid
5291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodinput_userauth_failure(int type, u_int32_t seq, void *ctxt)
5301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
5311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	Authctxt *authctxt = ctxt;
5321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	char *authlist = NULL;
5331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	int partial;
5341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
5351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (authctxt == NULL)
5361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		fatal("input_userauth_failure: no authentication context");
5371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
5381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	authlist = packet_get_string(NULL);
5391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	partial = packet_get_char();
5401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_check_eom();
5411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
5421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (partial != 0)
5431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		logit("Authenticated with partial success.");
5441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	debug("Authentications that can continue: %s", authlist);
5451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
5461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	userauth(authctxt, authlist);
5471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
5481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
5491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* ARGSUSED */
5501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodvoid
5511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodinput_userauth_pk_ok(int type, u_int32_t seq, void *ctxt)
5521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
5531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	Authctxt *authctxt = ctxt;
5541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	Key *key = NULL;
5551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	Identity *id = NULL;
5561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	Buffer b;
5571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	int pktype, sent = 0;
5581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	u_int alen, blen;
5591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	char *pkalg, *fp;
5601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	u_char *pkblob;
5611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
5621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (authctxt == NULL)
5631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		fatal("input_userauth_pk_ok: no authentication context");
5641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (datafellows & SSH_BUG_PKOK) {
5651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		/* this is similar to SSH_BUG_PKAUTH */
5661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		debug2("input_userauth_pk_ok: SSH_BUG_PKOK");
5671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		pkblob = packet_get_string(&blen);
5681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		buffer_init(&b);
5691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		buffer_append(&b, pkblob, blen);
5701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		pkalg = buffer_get_string(&b, &alen);
5711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		buffer_free(&b);
5721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	} else {
5731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		pkalg = packet_get_string(&alen);
5741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		pkblob = packet_get_string(&blen);
5751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
5761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_check_eom();
5771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
5781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	debug("Server accepts key: pkalg %s blen %u", pkalg, blen);
5791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
5801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if ((pktype = key_type_from_name(pkalg)) == KEY_UNSPEC) {
5811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		debug("unknown pkalg %s", pkalg);
5821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		goto done;
5831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
5841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if ((key = key_from_blob(pkblob, blen)) == NULL) {
5851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		debug("no key from blob. pkalg %s", pkalg);
5861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		goto done;
5871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
5881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (key->type != pktype) {
5891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		error("input_userauth_pk_ok: type mismatch "
5901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    "for decoded key (received %d, expected %d)",
5911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    key->type, pktype);
5921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		goto done;
5931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
5941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX);
5951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	debug2("input_userauth_pk_ok: fp %s", fp);
5961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	xfree(fp);
5971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
5981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/*
5991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * search keys in the reverse order, because last candidate has been
6001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * moved to the end of the queue.  this also avoids confusion by
6011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * duplicate keys
6021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 */
6031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	TAILQ_FOREACH_REVERSE(id, &authctxt->keys, idlist, next) {
6041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (key_equal(key, id->key)) {
6051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			sent = sign_and_send_pubkey(authctxt, id);
6061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			break;
6071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
6081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
6091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwooddone:
6101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (key != NULL)
6111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		key_free(key);
6121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	xfree(pkalg);
6131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	xfree(pkblob);
6141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
6151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* try another method if we did not send a packet */
6161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (sent == 0)
6171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		userauth(authctxt, NULL);
6181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
6191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
6201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifdef GSSAPI
6211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodint
6221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwooduserauth_gssapi(Authctxt *authctxt)
6231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
6241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	Gssctxt *gssctxt = NULL;
6251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	static gss_OID_set gss_supported = NULL;
6261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	static u_int mech = 0;
6271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	OM_uint32 min;
6281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	int ok = 0;
6291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
6301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* Try one GSSAPI method at a time, rather than sending them all at
6311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * once. */
6321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
6331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (gss_supported == NULL)
6341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		gss_indicate_mechs(&min, &gss_supported);
6351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
6361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* Check to see if the mechanism is usable before we offer it */
6371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	while (mech < gss_supported->count && !ok) {
6381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		/* My DER encoding requires length<128 */
6391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (gss_supported->elements[mech].length < 128 &&
6401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    ssh_gssapi_check_mechanism(&gssctxt,
6411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    &gss_supported->elements[mech], authctxt->host)) {
6421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			ok = 1; /* Mechanism works */
6431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		} else {
6441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			mech++;
6451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
6461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
6471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
6481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (!ok)
6491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return 0;
6501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
6511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	authctxt->methoddata=(void *)gssctxt;
6521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
6531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_start(SSH2_MSG_USERAUTH_REQUEST);
6541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_put_cstring(authctxt->server_user);
6551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_put_cstring(authctxt->service);
6561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_put_cstring(authctxt->method->name);
6571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
6581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_put_int(1);
6591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
6601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_put_int((gss_supported->elements[mech].length) + 2);
6611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_put_char(SSH_GSS_OIDTYPE);
6621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_put_char(gss_supported->elements[mech].length);
6631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_put_raw(gss_supported->elements[mech].elements,
6641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    gss_supported->elements[mech].length);
6651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
6661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_send();
6671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
6681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_RESPONSE, &input_gssapi_response);
6691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, &input_gssapi_token);
6701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_ERROR, &input_gssapi_error);
6711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_ERRTOK, &input_gssapi_errtok);
6721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
6731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	mech++; /* Move along to next candidate */
6741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
6751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	return 1;
6761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
6771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
6781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic OM_uint32
6791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodprocess_gssapi_token(void *ctxt, gss_buffer_t recv_tok)
6801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
6811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	Authctxt *authctxt = ctxt;
6821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	Gssctxt *gssctxt = authctxt->methoddata;
6831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	gss_buffer_desc send_tok = GSS_C_EMPTY_BUFFER;
6841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	gss_buffer_desc mic = GSS_C_EMPTY_BUFFER;
6851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	gss_buffer_desc gssbuf;
6861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	OM_uint32 status, ms, flags;
6871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	Buffer b;
6881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
6891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	status = ssh_gssapi_init_ctx(gssctxt, options.gss_deleg_creds,
6901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    recv_tok, &send_tok, &flags);
6911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
6921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (send_tok.length > 0) {
6931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (GSS_ERROR(status))
6941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			packet_start(SSH2_MSG_USERAUTH_GSSAPI_ERRTOK);
6951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		else
6961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			packet_start(SSH2_MSG_USERAUTH_GSSAPI_TOKEN);
6971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
6981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		packet_put_string(send_tok.value, send_tok.length);
6991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		packet_send();
7001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		gss_release_buffer(&ms, &send_tok);
7011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
7021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
7031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (status == GSS_S_COMPLETE) {
7041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		/* send either complete or MIC, depending on mechanism */
7051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (!(flags & GSS_C_INTEG_FLAG)) {
7061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			packet_start(SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE);
7071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			packet_send();
7081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		} else {
7091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			ssh_gssapi_buildmic(&b, authctxt->server_user,
7101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			    authctxt->service, "gssapi-with-mic");
7111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
7121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			gssbuf.value = buffer_ptr(&b);
7131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			gssbuf.length = buffer_len(&b);
7141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
7151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			status = ssh_gssapi_sign(gssctxt, &gssbuf, &mic);
7161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
7171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			if (!GSS_ERROR(status)) {
7181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				packet_start(SSH2_MSG_USERAUTH_GSSAPI_MIC);
7191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				packet_put_string(mic.value, mic.length);
7201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
7211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				packet_send();
7221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			}
7231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
7241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			buffer_free(&b);
7251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			gss_release_buffer(&ms, &mic);
7261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
7271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
7281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
7291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	return status;
7301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
7311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
7321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* ARGSUSED */
7331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodvoid
7341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodinput_gssapi_response(int type, u_int32_t plen, void *ctxt)
7351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
7361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	Authctxt *authctxt = ctxt;
7371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	Gssctxt *gssctxt;
7381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	int oidlen;
7391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	char *oidv;
7401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
7411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (authctxt == NULL)
7421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		fatal("input_gssapi_response: no authentication context");
7431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	gssctxt = authctxt->methoddata;
7441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
7451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* Setup our OID */
7461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	oidv = packet_get_string(&oidlen);
7471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
7481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (oidlen <= 2 ||
7491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    oidv[0] != SSH_GSS_OIDTYPE ||
7501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    oidv[1] != oidlen - 2) {
7511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		xfree(oidv);
7521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		debug("Badly encoded mechanism OID received");
7531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		userauth(authctxt, NULL);
7541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return;
7551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
7561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
7571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (!ssh_gssapi_check_oid(gssctxt, oidv + 2, oidlen - 2))
7581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		fatal("Server returned different OID than expected");
7591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
7601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_check_eom();
7611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
7621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	xfree(oidv);
7631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
7641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (GSS_ERROR(process_gssapi_token(ctxt, GSS_C_NO_BUFFER))) {
7651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		/* Start again with next method on list */
7661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		debug("Trying to start again");
7671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		userauth(authctxt, NULL);
7681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return;
7691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
7701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
7711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
7721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* ARGSUSED */
7731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodvoid
7741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodinput_gssapi_token(int type, u_int32_t plen, void *ctxt)
7751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
7761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	Authctxt *authctxt = ctxt;
7771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	gss_buffer_desc recv_tok;
7781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	OM_uint32 status;
7791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	u_int slen;
7801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
7811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (authctxt == NULL)
7821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		fatal("input_gssapi_response: no authentication context");
7831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
7841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	recv_tok.value = packet_get_string(&slen);
7851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	recv_tok.length = slen;	/* safe typecast */
7861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
7871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_check_eom();
7881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
7891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	status = process_gssapi_token(ctxt, &recv_tok);
7901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
7911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	xfree(recv_tok.value);
7921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
7931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (GSS_ERROR(status)) {
7941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		/* Start again with the next method in the list */
7951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		userauth(authctxt, NULL);
7961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return;
7971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
7981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
7991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
8001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* ARGSUSED */
8011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodvoid
8021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodinput_gssapi_errtok(int type, u_int32_t plen, void *ctxt)
8031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
8041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	Authctxt *authctxt = ctxt;
8051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	Gssctxt *gssctxt;
8061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	gss_buffer_desc send_tok = GSS_C_EMPTY_BUFFER;
8071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	gss_buffer_desc recv_tok;
8081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	OM_uint32 status, ms;
8091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	u_int len;
8101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
8111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (authctxt == NULL)
8121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		fatal("input_gssapi_response: no authentication context");
8131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	gssctxt = authctxt->methoddata;
8141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
8151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	recv_tok.value = packet_get_string(&len);
8161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	recv_tok.length = len;
8171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
8181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_check_eom();
8191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
8201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* Stick it into GSSAPI and see what it says */
8211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	status = ssh_gssapi_init_ctx(gssctxt, options.gss_deleg_creds,
8221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    &recv_tok, &send_tok, NULL);
8231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
8241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	xfree(recv_tok.value);
8251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	gss_release_buffer(&ms, &send_tok);
8261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
8271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* Server will be returning a failed packet after this one */
8281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
8291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
8301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* ARGSUSED */
8311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodvoid
8321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodinput_gssapi_error(int type, u_int32_t plen, void *ctxt)
8331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
8341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	OM_uint32 maj, min;
8351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	char *msg;
8361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	char *lang;
8371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
8381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	maj=packet_get_int();
8391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	min=packet_get_int();
8401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	msg=packet_get_string(NULL);
8411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	lang=packet_get_string(NULL);
8421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
8431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_check_eom();
8441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
8451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	debug("Server GSSAPI Error:\n%s", msg);
8461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	xfree(msg);
8471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	xfree(lang);
8481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
8491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif /* GSSAPI */
8501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
8511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodint
8521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwooduserauth_none(Authctxt *authctxt)
8531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
8541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* initial userauth request */
8551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_start(SSH2_MSG_USERAUTH_REQUEST);
8561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_put_cstring(authctxt->server_user);
8571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_put_cstring(authctxt->service);
8581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_put_cstring(authctxt->method->name);
8591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_send();
8601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	return 1;
8611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
8621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
8631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodint
8641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwooduserauth_passwd(Authctxt *authctxt)
8651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
8661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	static int attempt = 0;
8671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	char prompt[150];
8681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	char *password;
8691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	const char *host = options.host_key_alias ?  options.host_key_alias :
8701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    authctxt->host;
8711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
8721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (attempt++ >= options.number_of_password_prompts)
8731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return 0;
8741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
8751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (attempt != 1)
8761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		error("Permission denied, please try again.");
8771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
8781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	snprintf(prompt, sizeof(prompt), "%.30s@%.128s's password: ",
8791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    authctxt->server_user, host);
8801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	password = read_passphrase(prompt, 0);
8811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_start(SSH2_MSG_USERAUTH_REQUEST);
8821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_put_cstring(authctxt->server_user);
8831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_put_cstring(authctxt->service);
8841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_put_cstring(authctxt->method->name);
8851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_put_char(0);
8861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_put_cstring(password);
8871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	memset(password, 0, strlen(password));
8881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	xfree(password);
8891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_add_padding(64);
8901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_send();
8911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
8921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	dispatch_set(SSH2_MSG_USERAUTH_PASSWD_CHANGEREQ,
8931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    &input_userauth_passwd_changereq);
8941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
8951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	return 1;
8961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
8971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
8981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/*
8991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * parse PASSWD_CHANGEREQ, prompt user and send SSH2_MSG_USERAUTH_REQUEST
9001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood */
9011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* ARGSUSED */
9021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodvoid
9031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodinput_userauth_passwd_changereq(int type, u_int32_t seqnr, void *ctxt)
9041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
9051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	Authctxt *authctxt = ctxt;
9061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	char *info, *lang, *password = NULL, *retype = NULL;
9071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	char prompt[150];
9081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	const char *host = options.host_key_alias ? options.host_key_alias :
9091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    authctxt->host;
9101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
9111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	debug2("input_userauth_passwd_changereq");
9121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
9131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (authctxt == NULL)
9141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		fatal("input_userauth_passwd_changereq: "
9151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    "no authentication context");
9161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
9171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	info = packet_get_string(NULL);
9181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	lang = packet_get_string(NULL);
9191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (strlen(info) > 0)
9201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		logit("%s", info);
9211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	xfree(info);
9221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	xfree(lang);
9231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_start(SSH2_MSG_USERAUTH_REQUEST);
9241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_put_cstring(authctxt->server_user);
9251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_put_cstring(authctxt->service);
9261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_put_cstring(authctxt->method->name);
9271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_put_char(1);			/* additional info */
9281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	snprintf(prompt, sizeof(prompt),
9291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    "Enter %.30s@%.128s's old password: ",
9301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    authctxt->server_user, host);
9311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	password = read_passphrase(prompt, 0);
9321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_put_cstring(password);
9331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	memset(password, 0, strlen(password));
9341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	xfree(password);
9351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	password = NULL;
9361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	while (password == NULL) {
9371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		snprintf(prompt, sizeof(prompt),
9381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    "Enter %.30s@%.128s's new password: ",
9391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    authctxt->server_user, host);
9401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		password = read_passphrase(prompt, RP_ALLOW_EOF);
9411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (password == NULL) {
9421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			/* bail out */
9431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			return;
9441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
9451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		snprintf(prompt, sizeof(prompt),
9461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    "Retype %.30s@%.128s's new password: ",
9471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    authctxt->server_user, host);
9481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		retype = read_passphrase(prompt, 0);
9491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (strcmp(password, retype) != 0) {
9501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			memset(password, 0, strlen(password));
9511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			xfree(password);
9521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			logit("Mismatch; try again, EOF to quit.");
9531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			password = NULL;
9541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
9551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		memset(retype, 0, strlen(retype));
9561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		xfree(retype);
9571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
9581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_put_cstring(password);
9591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	memset(password, 0, strlen(password));
9601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	xfree(password);
9611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_add_padding(64);
9621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_send();
9631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
9641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	dispatch_set(SSH2_MSG_USERAUTH_PASSWD_CHANGEREQ,
9651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    &input_userauth_passwd_changereq);
9661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
9671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
9681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifdef JPAKE
9691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic char *
9701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodpw_encrypt(const char *password, const char *crypt_scheme, const char *salt)
9711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
9721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* OpenBSD crypt(3) handles all of these */
9731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (strcmp(crypt_scheme, "crypt") == 0 ||
9741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    strcmp(crypt_scheme, "bcrypt") == 0 ||
9751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    strcmp(crypt_scheme, "md5crypt") == 0 ||
9761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    strcmp(crypt_scheme, "crypt-extended") == 0)
9771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return xstrdup(crypt(password, salt));
9781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	error("%s: unsupported password encryption scheme \"%.100s\"",
9791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    __func__, crypt_scheme);
9801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	return NULL;
9811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
9821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
9831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic BIGNUM *
9841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodjpake_password_to_secret(Authctxt *authctxt, const char *crypt_scheme,
9851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood    const char *salt)
9861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
9871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	char prompt[256], *password, *crypted;
9881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	u_char *secret;
9891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	u_int secret_len;
9901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	BIGNUM *ret;
9911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
9921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	snprintf(prompt, sizeof(prompt), "%.30s@%.128s's password (JPAKE): ",
9931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    authctxt->server_user, authctxt->host);
9941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	password = read_passphrase(prompt, 0);
9951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
9961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if ((crypted = pw_encrypt(password, crypt_scheme, salt)) == NULL) {
9971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		logit("Disabling %s authentication", authctxt->method->name);
9981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		authctxt->method->enabled = NULL;
9991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		/* Continue with an empty password to fail gracefully */
10001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		crypted = xstrdup("");
10011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
10021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
10031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifdef JPAKE_DEBUG
10041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	debug3("%s: salt = %s", __func__, salt);
10051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	debug3("%s: scheme = %s", __func__, crypt_scheme);
10061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	debug3("%s: crypted = %s", __func__, crypted);
10071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif
10081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
10091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (hash_buffer(crypted, strlen(crypted), EVP_sha256(),
10101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    &secret, &secret_len) != 0)
10111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		fatal("%s: hash_buffer", __func__);
10121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
10131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	bzero(password, strlen(password));
10141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	bzero(crypted, strlen(crypted));
10151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	xfree(password);
10161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	xfree(crypted);
10171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
10181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if ((ret = BN_bin2bn(secret, secret_len, NULL)) == NULL)
10191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		fatal("%s: BN_bin2bn (secret)", __func__);
10201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	bzero(secret, secret_len);
10211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	xfree(secret);
10221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
10231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	return ret;
10241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
10251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
10261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* ARGSUSED */
10271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodvoid
10281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodinput_userauth_jpake_server_step1(int type, u_int32_t seq, void *ctxt)
10291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
10301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	Authctxt *authctxt = ctxt;
10311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	struct jpake_ctx *pctx = authctxt->methoddata;
10321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	u_char *x3_proof, *x4_proof, *x2_s_proof;
10331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	u_int x3_proof_len, x4_proof_len, x2_s_proof_len;
10341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	char *crypt_scheme, *salt;
10351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
10361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* Disable this message */
10371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	dispatch_set(SSH2_MSG_USERAUTH_JPAKE_SERVER_STEP1, NULL);
10381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
10391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if ((pctx->g_x3 = BN_new()) == NULL ||
10401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    (pctx->g_x4 = BN_new()) == NULL)
10411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		fatal("%s: BN_new", __func__);
10421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
10431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* Fetch step 1 values */
10441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	crypt_scheme = packet_get_string(NULL);
10451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	salt = packet_get_string(NULL);
10461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	pctx->server_id = packet_get_string(&pctx->server_id_len);
10471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_get_bignum2(pctx->g_x3);
10481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_get_bignum2(pctx->g_x4);
10491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	x3_proof = packet_get_string(&x3_proof_len);
10501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	x4_proof = packet_get_string(&x4_proof_len);
10511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_check_eom();
10521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
10531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	JPAKE_DEBUG_CTX((pctx, "step 1 received in %s", __func__));
10541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
10551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* Obtain password and derive secret */
10561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	pctx->s = jpake_password_to_secret(authctxt, crypt_scheme, salt);
10571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	bzero(crypt_scheme, strlen(crypt_scheme));
10581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	bzero(salt, strlen(salt));
10591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	xfree(crypt_scheme);
10601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	xfree(salt);
10611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	JPAKE_DEBUG_BN((pctx->s, "%s: s = ", __func__));
10621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
10631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* Calculate step 2 values */
10641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	jpake_step2(pctx->grp, pctx->s, pctx->g_x1,
10651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    pctx->g_x3, pctx->g_x4, pctx->x2,
10661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    pctx->server_id, pctx->server_id_len,
10671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    pctx->client_id, pctx->client_id_len,
10681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    x3_proof, x3_proof_len,
10691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    x4_proof, x4_proof_len,
10701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    &pctx->a,
10711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    &x2_s_proof, &x2_s_proof_len);
10721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
10731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	bzero(x3_proof, x3_proof_len);
10741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	bzero(x4_proof, x4_proof_len);
10751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	xfree(x3_proof);
10761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	xfree(x4_proof);
10771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
10781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	JPAKE_DEBUG_CTX((pctx, "step 2 sending in %s", __func__));
10791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
10801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* Send values for step 2 */
10811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_start(SSH2_MSG_USERAUTH_JPAKE_CLIENT_STEP2);
10821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_put_bignum2(pctx->a);
10831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_put_string(x2_s_proof, x2_s_proof_len);
10841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_send();
10851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
10861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	bzero(x2_s_proof, x2_s_proof_len);
10871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	xfree(x2_s_proof);
10881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
10891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* Expect step 2 packet from peer */
10901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	dispatch_set(SSH2_MSG_USERAUTH_JPAKE_SERVER_STEP2,
10911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    input_userauth_jpake_server_step2);
10921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
10931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
10941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* ARGSUSED */
10951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodvoid
10961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodinput_userauth_jpake_server_step2(int type, u_int32_t seq, void *ctxt)
10971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
10981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	Authctxt *authctxt = ctxt;
10991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	struct jpake_ctx *pctx = authctxt->methoddata;
11001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	u_char *x4_s_proof;
11011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	u_int x4_s_proof_len;
11021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
11031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* Disable this message */
11041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	dispatch_set(SSH2_MSG_USERAUTH_JPAKE_SERVER_STEP2, NULL);
11051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
11061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if ((pctx->b = BN_new()) == NULL)
11071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		fatal("%s: BN_new", __func__);
11081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
11091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* Fetch step 2 values */
11101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_get_bignum2(pctx->b);
11111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	x4_s_proof = packet_get_string(&x4_s_proof_len);
11121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_check_eom();
11131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
11141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	JPAKE_DEBUG_CTX((pctx, "step 2 received in %s", __func__));
11151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
11161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* Derive shared key and calculate confirmation hash */
11171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	jpake_key_confirm(pctx->grp, pctx->s, pctx->b,
11181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    pctx->x2, pctx->g_x1, pctx->g_x2, pctx->g_x3, pctx->g_x4,
11191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    pctx->client_id, pctx->client_id_len,
11201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    pctx->server_id, pctx->server_id_len,
11211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    session_id2, session_id2_len,
11221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    x4_s_proof, x4_s_proof_len,
11231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    &pctx->k,
11241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    &pctx->h_k_cid_sessid, &pctx->h_k_cid_sessid_len);
11251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
11261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	bzero(x4_s_proof, x4_s_proof_len);
11271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	xfree(x4_s_proof);
11281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
11291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	JPAKE_DEBUG_CTX((pctx, "confirm sending in %s", __func__));
11301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
11311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* Send key confirmation proof */
11321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_start(SSH2_MSG_USERAUTH_JPAKE_CLIENT_CONFIRM);
11331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_put_string(pctx->h_k_cid_sessid, pctx->h_k_cid_sessid_len);
11341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_send();
11351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
11361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* Expect confirmation from peer */
11371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	dispatch_set(SSH2_MSG_USERAUTH_JPAKE_SERVER_CONFIRM,
11381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    input_userauth_jpake_server_confirm);
11391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
11401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
11411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* ARGSUSED */
11421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodvoid
11431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodinput_userauth_jpake_server_confirm(int type, u_int32_t seq, void *ctxt)
11441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
11451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	Authctxt *authctxt = ctxt;
11461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	struct jpake_ctx *pctx = authctxt->methoddata;
11471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
11481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* Disable this message */
11491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	dispatch_set(SSH2_MSG_USERAUTH_JPAKE_SERVER_CONFIRM, NULL);
11501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
11511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	pctx->h_k_sid_sessid = packet_get_string(&pctx->h_k_sid_sessid_len);
11521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_check_eom();
11531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
11541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	JPAKE_DEBUG_CTX((pctx, "confirm received in %s", __func__));
11551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
11561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* Verify expected confirmation hash */
11571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (jpake_check_confirm(pctx->k,
11581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    pctx->server_id, pctx->server_id_len,
11591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    session_id2, session_id2_len,
11601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    pctx->h_k_sid_sessid, pctx->h_k_sid_sessid_len) == 1)
11611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		debug("%s: %s success", __func__, authctxt->method->name);
11621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	else {
11631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		debug("%s: confirmation mismatch", __func__);
11641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		/* XXX stash this so if auth succeeds then we can warn/kill */
11651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
11661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
11671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	userauth_jpake_cleanup(authctxt);
11681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
11691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif /* JPAKE */
11701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
11711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic int
11721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodidentity_sign(Identity *id, u_char **sigp, u_int *lenp,
11731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood    u_char *data, u_int datalen)
11741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
11751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	Key *prv;
11761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	int ret;
11771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
11781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* the agent supports this key */
11791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (id->ac)
11801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return (ssh_agent_sign(id->ac, id->key, sigp, lenp,
11811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    data, datalen));
11821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/*
11831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * we have already loaded the private key or
11841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * the private key is stored in external hardware
11851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 */
11861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (id->isprivate || (id->key->flags & KEY_FLAG_EXT))
11871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return (key_sign(id->key, sigp, lenp, data, datalen));
11881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* load the private key from the file */
11891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if ((prv = load_identity_file(id->filename)) == NULL)
11901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return (-1);
11911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	ret = key_sign(prv, sigp, lenp, data, datalen);
11921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	key_free(prv);
11931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	return (ret);
11941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
11951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
11961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic int
11971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodsign_and_send_pubkey(Authctxt *authctxt, Identity *id)
11981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
11991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	Buffer b;
12001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	u_char *blob, *signature;
12011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	u_int bloblen, slen;
12021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	u_int skip = 0;
12031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	int ret = -1;
12041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	int have_sig = 1;
12051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	char *fp;
12061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
12071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	fp = key_fingerprint(id->key, SSH_FP_MD5, SSH_FP_HEX);
12081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	debug3("sign_and_send_pubkey: %s %s", key_type(id->key), fp);
12091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	xfree(fp);
12101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
12111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (key_to_blob(id->key, &blob, &bloblen) == 0) {
12121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		/* we cannot handle this key */
12131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		debug3("sign_and_send_pubkey: cannot handle key");
12141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return 0;
12151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
12161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* data to be signed */
12171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	buffer_init(&b);
12181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (datafellows & SSH_OLD_SESSIONID) {
12191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		buffer_append(&b, session_id2, session_id2_len);
12201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		skip = session_id2_len;
12211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	} else {
12221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		buffer_put_string(&b, session_id2, session_id2_len);
12231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		skip = buffer_len(&b);
12241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
12251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	buffer_put_char(&b, SSH2_MSG_USERAUTH_REQUEST);
12261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	buffer_put_cstring(&b, authctxt->server_user);
12271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	buffer_put_cstring(&b,
12281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    datafellows & SSH_BUG_PKSERVICE ?
12291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    "ssh-userauth" :
12301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    authctxt->service);
12311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (datafellows & SSH_BUG_PKAUTH) {
12321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		buffer_put_char(&b, have_sig);
12331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	} else {
12341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		buffer_put_cstring(&b, authctxt->method->name);
12351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		buffer_put_char(&b, have_sig);
12361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		buffer_put_cstring(&b, key_ssh_name(id->key));
12371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
12381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	buffer_put_string(&b, blob, bloblen);
12391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
12401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* generate signature */
12411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	ret = identity_sign(id, &signature, &slen,
12421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    buffer_ptr(&b), buffer_len(&b));
12431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (ret == -1) {
12441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		xfree(blob);
12451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		buffer_free(&b);
12461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return 0;
12471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
12481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifdef DEBUG_PK
12491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	buffer_dump(&b);
12501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif
12511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (datafellows & SSH_BUG_PKSERVICE) {
12521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		buffer_clear(&b);
12531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		buffer_append(&b, session_id2, session_id2_len);
12541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		skip = session_id2_len;
12551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		buffer_put_char(&b, SSH2_MSG_USERAUTH_REQUEST);
12561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		buffer_put_cstring(&b, authctxt->server_user);
12571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		buffer_put_cstring(&b, authctxt->service);
12581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		buffer_put_cstring(&b, authctxt->method->name);
12591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		buffer_put_char(&b, have_sig);
12601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (!(datafellows & SSH_BUG_PKAUTH))
12611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			buffer_put_cstring(&b, key_ssh_name(id->key));
12621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		buffer_put_string(&b, blob, bloblen);
12631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
12641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	xfree(blob);
12651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
12661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* append signature */
12671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	buffer_put_string(&b, signature, slen);
12681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	xfree(signature);
12691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
12701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* skip session id and packet type */
12711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (buffer_len(&b) < skip + 1)
12721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		fatal("userauth_pubkey: internal error");
12731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	buffer_consume(&b, skip + 1);
12741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
12751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* put remaining data from buffer into packet */
12761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_start(SSH2_MSG_USERAUTH_REQUEST);
12771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_put_raw(buffer_ptr(&b), buffer_len(&b));
12781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	buffer_free(&b);
12791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_send();
12801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
12811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	return 1;
12821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
12831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
12841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic int
12851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodsend_pubkey_test(Authctxt *authctxt, Identity *id)
12861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
12871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	u_char *blob;
12881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	u_int bloblen, have_sig = 0;
12891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
12901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	debug3("send_pubkey_test");
12911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
12921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (key_to_blob(id->key, &blob, &bloblen) == 0) {
12931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		/* we cannot handle this key */
12941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		debug3("send_pubkey_test: cannot handle key");
12951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return 0;
12961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
12971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* register callback for USERAUTH_PK_OK message */
12981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	dispatch_set(SSH2_MSG_USERAUTH_PK_OK, &input_userauth_pk_ok);
12991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
13001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_start(SSH2_MSG_USERAUTH_REQUEST);
13011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_put_cstring(authctxt->server_user);
13021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_put_cstring(authctxt->service);
13031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_put_cstring(authctxt->method->name);
13041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_put_char(have_sig);
13051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (!(datafellows & SSH_BUG_PKAUTH))
13061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		packet_put_cstring(key_ssh_name(id->key));
13071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_put_string(blob, bloblen);
13081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	xfree(blob);
13091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_send();
13101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	return 1;
13111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
13121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
13131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic Key *
13141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodload_identity_file(char *filename)
13151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
13161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	Key *private;
13171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	char prompt[300], *passphrase;
13181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	int perm_ok = 0, quit, i;
13191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	struct stat st;
13201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
13211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (stat(filename, &st) < 0) {
13221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		debug3("no such identity: %s", filename);
13231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return NULL;
13241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
13251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	private = key_load_private_type(KEY_UNSPEC, filename, "", NULL, &perm_ok);
13261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (!perm_ok)
13271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return NULL;
13281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (private == NULL) {
13291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (options.batch_mode)
13301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			return NULL;
13311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		snprintf(prompt, sizeof prompt,
13321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    "Enter passphrase for key '%.100s': ", filename);
13331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		for (i = 0; i < options.number_of_password_prompts; i++) {
13341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			passphrase = read_passphrase(prompt, 0);
13351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			if (strcmp(passphrase, "") != 0) {
13361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				private = key_load_private_type(KEY_UNSPEC,
13371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				    filename, passphrase, NULL, NULL);
13381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				quit = 0;
13391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			} else {
13401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				debug2("no passphrase given, try next key");
13411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				quit = 1;
13421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			}
13431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			memset(passphrase, 0, strlen(passphrase));
13441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			xfree(passphrase);
13451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			if (private != NULL || quit)
13461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				break;
13471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			debug2("bad passphrase given, try again...");
13481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
13491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
13501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	return private;
13511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
13521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
13531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/*
13541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * try keys in the following order:
13551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *	1. agent keys that are found in the config file
13561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *	2. other agent keys
13571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *	3. keys that are only listed in the config file
13581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood */
13591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic void
13601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodpubkey_prepare(Authctxt *authctxt)
13611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
13621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	Identity *id;
13631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	Idlist agent, files, *preferred;
13641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	Key *key;
13651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	AuthenticationConnection *ac;
13661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	char *comment;
13671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	int i, found;
13681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
13691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	TAILQ_INIT(&agent);	/* keys from the agent */
13701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	TAILQ_INIT(&files);	/* keys from the config file */
13711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	preferred = &authctxt->keys;
13721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	TAILQ_INIT(preferred);	/* preferred order of keys */
13731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
13741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* list of keys stored in the filesystem */
13751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	for (i = 0; i < options.num_identity_files; i++) {
13761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		key = options.identity_keys[i];
13771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (key && key->type == KEY_RSA1)
13781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			continue;
13791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (key && key->cert && key->cert->type != SSH2_CERT_TYPE_USER)
13801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			continue;
13811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		options.identity_keys[i] = NULL;
13821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		id = xcalloc(1, sizeof(*id));
13831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		id->key = key;
13841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		id->filename = xstrdup(options.identity_files[i]);
13851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		TAILQ_INSERT_TAIL(&files, id, next);
13861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
13871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* list of keys supported by the agent */
13881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if ((ac = ssh_get_authentication_connection())) {
13891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		for (key = ssh_get_first_identity(ac, &comment, 2);
13901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    key != NULL;
13911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    key = ssh_get_next_identity(ac, &comment, 2)) {
13921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			found = 0;
13931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			TAILQ_FOREACH(id, &files, next) {
13941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				/* agent keys from the config file are preferred */
13951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				if (key_equal(key, id->key)) {
13961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					key_free(key);
13971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					xfree(comment);
13981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					TAILQ_REMOVE(&files, id, next);
13991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					TAILQ_INSERT_TAIL(preferred, id, next);
14001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					id->ac = ac;
14011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					found = 1;
14021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					break;
14031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				}
14041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			}
14051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			if (!found && !options.identities_only) {
14061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				id = xcalloc(1, sizeof(*id));
14071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				id->key = key;
14081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				id->filename = comment;
14091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				id->ac = ac;
14101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				TAILQ_INSERT_TAIL(&agent, id, next);
14111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			}
14121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
14131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		/* append remaining agent keys */
14141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		for (id = TAILQ_FIRST(&agent); id; id = TAILQ_FIRST(&agent)) {
14151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			TAILQ_REMOVE(&agent, id, next);
14161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			TAILQ_INSERT_TAIL(preferred, id, next);
14171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
14181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		authctxt->agent = ac;
14191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
14201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* append remaining keys from the config file */
14211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	for (id = TAILQ_FIRST(&files); id; id = TAILQ_FIRST(&files)) {
14221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		TAILQ_REMOVE(&files, id, next);
14231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		TAILQ_INSERT_TAIL(preferred, id, next);
14241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
14251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	TAILQ_FOREACH(id, preferred, next) {
14261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		debug2("key: %s (%p)", id->filename, id->key);
14271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
14281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
14291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
14301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic void
14311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodpubkey_cleanup(Authctxt *authctxt)
14321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
14331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	Identity *id;
14341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
14351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (authctxt->agent != NULL)
14361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		ssh_close_authentication_connection(authctxt->agent);
14371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	for (id = TAILQ_FIRST(&authctxt->keys); id;
14381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    id = TAILQ_FIRST(&authctxt->keys)) {
14391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		TAILQ_REMOVE(&authctxt->keys, id, next);
14401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (id->key)
14411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			key_free(id->key);
14421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (id->filename)
14431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			xfree(id->filename);
14441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		xfree(id);
14451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
14461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
14471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
14481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodint
14491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwooduserauth_pubkey(Authctxt *authctxt)
14501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
14511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	Identity *id;
14521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	int sent = 0;
14531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
14541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	while ((id = TAILQ_FIRST(&authctxt->keys))) {
14551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (id->tried++)
14561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			return (0);
14571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		/* move key to the end of the queue */
14581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		TAILQ_REMOVE(&authctxt->keys, id, next);
14591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		TAILQ_INSERT_TAIL(&authctxt->keys, id, next);
14601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		/*
14611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		 * send a test message if we have the public key. for
14621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		 * encrypted keys we cannot do this and have to load the
14631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		 * private key instead
14641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		 */
14651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (id->key && id->key->type != KEY_RSA1) {
14661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			debug("Offering %s public key: %s", key_type(id->key),
14671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			    id->filename);
14681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			sent = send_pubkey_test(authctxt, id);
14691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		} else if (id->key == NULL) {
14701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			debug("Trying private key: %s", id->filename);
14711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			id->key = load_identity_file(id->filename);
14721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			if (id->key != NULL) {
14731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				id->isprivate = 1;
14741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				sent = sign_and_send_pubkey(authctxt, id);
14751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				key_free(id->key);
14761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				id->key = NULL;
14771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			}
14781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
14791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (sent)
14801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			return (sent);
14811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
14821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	return (0);
14831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
14841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
14851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/*
14861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Send userauth request message specifying keyboard-interactive method.
14871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood */
14881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodint
14891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwooduserauth_kbdint(Authctxt *authctxt)
14901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
14911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	static int attempt = 0;
14921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
14931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (attempt++ >= options.number_of_password_prompts)
14941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return 0;
14951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* disable if no SSH2_MSG_USERAUTH_INFO_REQUEST has been seen */
14961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (attempt > 1 && !authctxt->info_req_seen) {
14971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		debug3("userauth_kbdint: disable: no info_req_seen");
14981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		dispatch_set(SSH2_MSG_USERAUTH_INFO_REQUEST, NULL);
14991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return 0;
15001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
15011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
15021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	debug2("userauth_kbdint");
15031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_start(SSH2_MSG_USERAUTH_REQUEST);
15041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_put_cstring(authctxt->server_user);
15051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_put_cstring(authctxt->service);
15061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_put_cstring(authctxt->method->name);
15071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_put_cstring("");					/* lang */
15081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_put_cstring(options.kbd_interactive_devices ?
15091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    options.kbd_interactive_devices : "");
15101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_send();
15111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
15121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	dispatch_set(SSH2_MSG_USERAUTH_INFO_REQUEST, &input_userauth_info_req);
15131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	return 1;
15141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
15151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
15161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/*
15171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * parse INFO_REQUEST, prompt user and send INFO_RESPONSE
15181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood */
15191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodvoid
15201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodinput_userauth_info_req(int type, u_int32_t seq, void *ctxt)
15211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
15221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	Authctxt *authctxt = ctxt;
15231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	char *name, *inst, *lang, *prompt, *response;
15241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	u_int num_prompts, i;
15251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	int echo = 0;
15261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
15271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	debug2("input_userauth_info_req");
15281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
15291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (authctxt == NULL)
15301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		fatal("input_userauth_info_req: no authentication context");
15311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
15321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	authctxt->info_req_seen = 1;
15331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
15341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	name = packet_get_string(NULL);
15351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	inst = packet_get_string(NULL);
15361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	lang = packet_get_string(NULL);
15371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (strlen(name) > 0)
15381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		logit("%s", name);
15391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (strlen(inst) > 0)
15401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		logit("%s", inst);
15411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	xfree(name);
15421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	xfree(inst);
15431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	xfree(lang);
15441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
15451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	num_prompts = packet_get_int();
15461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/*
15471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * Begin to build info response packet based on prompts requested.
15481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * We commit to providing the correct number of responses, so if
15491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * further on we run into a problem that prevents this, we have to
15501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * be sure and clean this up and send a correct error response.
15511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 */
15521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_start(SSH2_MSG_USERAUTH_INFO_RESPONSE);
15531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_put_int(num_prompts);
15541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
15551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	debug2("input_userauth_info_req: num_prompts %d", num_prompts);
15561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	for (i = 0; i < num_prompts; i++) {
15571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		prompt = packet_get_string(NULL);
15581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		echo = packet_get_char();
15591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
15601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		response = read_passphrase(prompt, echo ? RP_ECHO : 0);
15611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
15621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		packet_put_cstring(response);
15631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		memset(response, 0, strlen(response));
15641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		xfree(response);
15651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		xfree(prompt);
15661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
15671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_check_eom(); /* done with parsing incoming message. */
15681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
15691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_add_padding(64);
15701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_send();
15711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
15721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
15731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic int
15741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodssh_keysign(Key *key, u_char **sigp, u_int *lenp,
15751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood    u_char *data, u_int datalen)
15761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
15771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	Buffer b;
15781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	struct stat st;
15791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	pid_t pid;
15801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	int to[2], from[2], status, version = 2;
15811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
15821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	debug2("ssh_keysign called");
15831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
15841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (stat(_PATH_SSH_KEY_SIGN, &st) < 0) {
15851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		error("ssh_keysign: not installed: %s", strerror(errno));
15861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return -1;
15871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
15881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (fflush(stdout) != 0)
15891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		error("ssh_keysign: fflush: %s", strerror(errno));
15901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (pipe(to) < 0) {
15911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		error("ssh_keysign: pipe: %s", strerror(errno));
15921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return -1;
15931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
15941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (pipe(from) < 0) {
15951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		error("ssh_keysign: pipe: %s", strerror(errno));
15961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return -1;
15971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
15981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if ((pid = fork()) < 0) {
15991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		error("ssh_keysign: fork: %s", strerror(errno));
16001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return -1;
16011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
16021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (pid == 0) {
16031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		/* keep the socket on exec */
16041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		fcntl(packet_get_connection_in(), F_SETFD, 0);
16051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		permanently_drop_suid(getuid());
16061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		close(from[0]);
16071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (dup2(from[1], STDOUT_FILENO) < 0)
16081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			fatal("ssh_keysign: dup2: %s", strerror(errno));
16091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		close(to[1]);
16101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (dup2(to[0], STDIN_FILENO) < 0)
16111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			fatal("ssh_keysign: dup2: %s", strerror(errno));
16121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		close(from[1]);
16131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		close(to[0]);
16141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		execl(_PATH_SSH_KEY_SIGN, _PATH_SSH_KEY_SIGN, (char *) 0);
16151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		fatal("ssh_keysign: exec(%s): %s", _PATH_SSH_KEY_SIGN,
16161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    strerror(errno));
16171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
16181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	close(from[1]);
16191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	close(to[0]);
16201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
16211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	buffer_init(&b);
16221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	buffer_put_int(&b, packet_get_connection_in()); /* send # of socket */
16231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	buffer_put_string(&b, data, datalen);
16241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (ssh_msg_send(to[1], version, &b) == -1)
16251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		fatal("ssh_keysign: couldn't send request");
16261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
16271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (ssh_msg_recv(from[0], &b) < 0) {
16281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		error("ssh_keysign: no reply");
16291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		buffer_free(&b);
16301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return -1;
16311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
16321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	close(from[0]);
16331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	close(to[1]);
16341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
16351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	while (waitpid(pid, &status, 0) < 0)
16361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (errno != EINTR)
16371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			break;
16381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
16391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (buffer_get_char(&b) != version) {
16401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		error("ssh_keysign: bad version");
16411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		buffer_free(&b);
16421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return -1;
16431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
16441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	*sigp = buffer_get_string(&b, lenp);
16451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	buffer_free(&b);
16461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
16471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	return 0;
16481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
16491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
16501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodint
16511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwooduserauth_hostbased(Authctxt *authctxt)
16521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
16531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	Key *private = NULL;
16541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	Sensitive *sensitive = authctxt->sensitive;
16551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	Buffer b;
16561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	u_char *signature, *blob;
16571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	char *chost, *pkalg, *p;
16581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	const char *service;
16591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	u_int blen, slen;
16601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	int ok, i, found = 0;
16611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
16621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* check for a useful key */
16631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	for (i = 0; i < sensitive->nkeys; i++) {
16641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		private = sensitive->keys[i];
16651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (private && private->type != KEY_RSA1) {
16661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			found = 1;
16671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			/* we take and free the key */
16681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			sensitive->keys[i] = NULL;
16691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			break;
16701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
16711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
16721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (!found) {
16731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		debug("No more client hostkeys for hostbased authentication.");
16741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return 0;
16751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
16761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (key_to_blob(private, &blob, &blen) == 0) {
16771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		key_free(private);
16781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return 0;
16791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
16801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* figure out a name for the client host */
16811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	p = get_local_name(packet_get_connection_in());
16821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (p == NULL) {
16831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		error("userauth_hostbased: cannot get local ipaddr/name");
16841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		key_free(private);
16851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		xfree(blob);
16861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return 0;
16871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
16881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	xasprintf(&chost, "%s.", p);
16891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	debug2("userauth_hostbased: chost %s", chost);
16901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	xfree(p);
16911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
16921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	service = datafellows & SSH_BUG_HBSERVICE ? "ssh-userauth" :
16931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    authctxt->service;
16941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	pkalg = xstrdup(key_ssh_name(private));
16951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	buffer_init(&b);
16961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* construct data */
16971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	buffer_put_string(&b, session_id2, session_id2_len);
16981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	buffer_put_char(&b, SSH2_MSG_USERAUTH_REQUEST);
16991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	buffer_put_cstring(&b, authctxt->server_user);
17001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	buffer_put_cstring(&b, service);
17011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	buffer_put_cstring(&b, authctxt->method->name);
17021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	buffer_put_cstring(&b, pkalg);
17031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	buffer_put_string(&b, blob, blen);
17041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	buffer_put_cstring(&b, chost);
17051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	buffer_put_cstring(&b, authctxt->local_user);
17061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifdef DEBUG_PK
17071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	buffer_dump(&b);
17081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif
17091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (sensitive->external_keysign)
17101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		ok = ssh_keysign(private, &signature, &slen,
17111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    buffer_ptr(&b), buffer_len(&b));
17121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	else
17131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		ok = key_sign(private, &signature, &slen,
17141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    buffer_ptr(&b), buffer_len(&b));
17151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	key_free(private);
17161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	buffer_free(&b);
17171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (ok != 0) {
17181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		error("key_sign failed");
17191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		xfree(chost);
17201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		xfree(pkalg);
17211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		xfree(blob);
17221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return 0;
17231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
17241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_start(SSH2_MSG_USERAUTH_REQUEST);
17251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_put_cstring(authctxt->server_user);
17261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_put_cstring(authctxt->service);
17271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_put_cstring(authctxt->method->name);
17281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_put_cstring(pkalg);
17291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_put_string(blob, blen);
17301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_put_cstring(chost);
17311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_put_cstring(authctxt->local_user);
17321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_put_string(signature, slen);
17331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	memset(signature, 's', slen);
17341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	xfree(signature);
17351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	xfree(chost);
17361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	xfree(pkalg);
17371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	xfree(blob);
17381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
17391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_send();
17401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	return 1;
17411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
17421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
17431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifdef JPAKE
17441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodint
17451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwooduserauth_jpake(Authctxt *authctxt)
17461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
17471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	struct jpake_ctx *pctx;
17481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	u_char *x1_proof, *x2_proof;
17491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	u_int x1_proof_len, x2_proof_len;
17501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	static int attempt = 0; /* XXX share with userauth_password's? */
17511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
17521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (attempt++ >= options.number_of_password_prompts)
17531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return 0;
17541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (attempt != 1)
17551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		error("Permission denied, please try again.");
17561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
17571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (authctxt->methoddata != NULL)
17581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		fatal("%s: authctxt->methoddata already set (%p)",
17591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    __func__, authctxt->methoddata);
17601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
17611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	authctxt->methoddata = pctx = jpake_new();
17621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
17631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/*
17641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * Send request immediately, to get the protocol going while
17651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * we do the initial computations.
17661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 */
17671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_start(SSH2_MSG_USERAUTH_REQUEST);
17681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_put_cstring(authctxt->server_user);
17691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_put_cstring(authctxt->service);
17701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_put_cstring(authctxt->method->name);
17711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_send();
17721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_write_wait();
17731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
17741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	jpake_step1(pctx->grp,
17751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    &pctx->client_id, &pctx->client_id_len,
17761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    &pctx->x1, &pctx->x2, &pctx->g_x1, &pctx->g_x2,
17771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    &x1_proof, &x1_proof_len,
17781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    &x2_proof, &x2_proof_len);
17791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
17801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	JPAKE_DEBUG_CTX((pctx, "step 1 sending in %s", __func__));
17811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
17821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_start(SSH2_MSG_USERAUTH_JPAKE_CLIENT_STEP1);
17831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_put_string(pctx->client_id, pctx->client_id_len);
17841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_put_bignum2(pctx->g_x1);
17851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_put_bignum2(pctx->g_x2);
17861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_put_string(x1_proof, x1_proof_len);
17871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_put_string(x2_proof, x2_proof_len);
17881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_send();
17891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
17901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	bzero(x1_proof, x1_proof_len);
17911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	bzero(x2_proof, x2_proof_len);
17921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	xfree(x1_proof);
17931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	xfree(x2_proof);
17941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
17951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* Expect step 1 packet from peer */
17961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	dispatch_set(SSH2_MSG_USERAUTH_JPAKE_SERVER_STEP1,
17971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    input_userauth_jpake_server_step1);
17981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	dispatch_set(SSH2_MSG_USERAUTH_SUCCESS,
17991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    &input_userauth_success_unexpected);
18001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
18011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	return 1;
18021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
18031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
18041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodvoid
18051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwooduserauth_jpake_cleanup(Authctxt *authctxt)
18061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
18071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	debug3("%s: clean up", __func__);
18081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (authctxt->methoddata != NULL) {
18091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		jpake_free(authctxt->methoddata);
18101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		authctxt->methoddata = NULL;
18111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
18121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	dispatch_set(SSH2_MSG_USERAUTH_SUCCESS, &input_userauth_success);
18131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
18141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif /* JPAKE */
18151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
18161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* find auth method */
18171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
18181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/*
18191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * given auth method name, if configurable options permit this method fill
18201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * in auth_ident field and return true, otherwise return false.
18211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood */
18221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic int
18231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodauthmethod_is_enabled(Authmethod *method)
18241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
18251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (method == NULL)
18261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return 0;
18271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* return false if options indicate this method is disabled */
18281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if  (method->enabled == NULL || *method->enabled == 0)
18291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return 0;
18301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* return false if batch mode is enabled but method needs interactive mode */
18311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if  (method->batch_flag != NULL && *method->batch_flag != 0)
18321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return 0;
18331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	return 1;
18341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
18351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
18361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic Authmethod *
18371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodauthmethod_lookup(const char *name)
18381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
18391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	Authmethod *method = NULL;
18401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (name != NULL)
18411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		for (method = authmethods; method->name != NULL; method++)
18421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			if (strcmp(name, method->name) == 0)
18431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				return method;
18441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	debug2("Unrecognized authentication method name: %s", name ? name : "NULL");
18451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	return NULL;
18461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
18471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
18481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* XXX internal state */
18491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic Authmethod *current = NULL;
18501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic char *supported = NULL;
18511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic char *preferred = NULL;
18521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
18531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/*
18541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Given the authentication method list sent by the server, return the
18551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * next method we should try.  If the server initially sends a nil list,
18561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * use a built-in default list.
18571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood */
18581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic Authmethod *
18591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodauthmethod_get(char *authlist)
18601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
18611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	char *name = NULL;
18621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	u_int next;
18631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
18641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* Use a suitable default if we're passed a nil list.  */
18651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (authlist == NULL || strlen(authlist) == 0)
18661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		authlist = options.preferred_authentications;
18671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
18681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (supported == NULL || strcmp(authlist, supported) != 0) {
18691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		debug3("start over, passed a different list %s", authlist);
18701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (supported != NULL)
18711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			xfree(supported);
18721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		supported = xstrdup(authlist);
18731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		preferred = options.preferred_authentications;
18741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		debug3("preferred %s", preferred);
18751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		current = NULL;
18761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	} else if (current != NULL && authmethod_is_enabled(current))
18771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return current;
18781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
18791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	for (;;) {
18801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if ((name = match_list(preferred, supported, &next)) == NULL) {
18811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			debug("No more authentication methods to try.");
18821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			current = NULL;
18831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			return NULL;
18841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
18851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		preferred += next;
18861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		debug3("authmethod_lookup %s", name);
18871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		debug3("remaining preferred: %s", preferred);
18881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if ((current = authmethod_lookup(name)) != NULL &&
18891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    authmethod_is_enabled(current)) {
18901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			debug3("authmethod_is_enabled %s", name);
18911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			debug("Next authentication method: %s", name);
18921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			xfree(name);
18931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			return current;
18941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
18951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
18961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (name != NULL)
18971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		xfree(name);
18981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
18991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
19001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic char *
19011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodauthmethods_get(void)
19021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
19031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	Authmethod *method = NULL;
19041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	Buffer b;
19051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	char *list;
19061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
19071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	buffer_init(&b);
19081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	for (method = authmethods; method->name != NULL; method++) {
19091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (authmethod_is_enabled(method)) {
19101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			if (buffer_len(&b) > 0)
19111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				buffer_append(&b, ",", 1);
19121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			buffer_append(&b, method->name, strlen(method->name));
19131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
19141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
19151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	buffer_append(&b, "\0", 1);
19161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	list = xstrdup(buffer_ptr(&b));
19171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	buffer_free(&b);
19181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	return list;
19191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
19201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1921