upstream commit

Add a ssh_config HostbasedKeyType option to control which
 host public key types are tried during hostbased authentication.

This may be used to prevent too many keys being sent to the server,
and blowing past its MaxAuthTries limit.

bz#2211 based on patch by Iain Morgan; ok markus@
diff --git a/readconf.c b/readconf.c
index 401f343..dd78da5 100644
--- a/readconf.c
+++ b/readconf.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: readconf.c,v 1.229 2015/01/26 03:04:45 djm Exp $ */
+/* $OpenBSD: readconf.c,v 1.230 2015/01/30 11:43:14 djm Exp $ */
 /*
  * Author: Tatu Ylonen <ylo@cs.hut.fi>
  * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -156,7 +156,7 @@
 	oCanonicalDomains, oCanonicalizeHostname, oCanonicalizeMaxDots,
 	oCanonicalizeFallbackLocal, oCanonicalizePermittedCNAMEs,
 	oStreamLocalBindMask, oStreamLocalBindUnlink, oRevokedHostKeys,
-	oFingerprintHash, oUpdateHostkeys,
+	oFingerprintHash, oUpdateHostkeys, oHostbasedKeyTypes,
 	oIgnoredUnknownOption, oDeprecated, oUnsupported
 } OpCodes;
 
@@ -274,6 +274,7 @@
 	{ "revokedhostkeys", oRevokedHostKeys },
 	{ "fingerprinthash", oFingerprintHash },
 	{ "updatehostkeys", oUpdateHostkeys },
+	{ "hostbasedkeytypes", oHostbasedKeyTypes },
 	{ "ignoreunknown", oIgnoreUnknown },
 
 	{ NULL, oBadOption }
@@ -1481,6 +1482,19 @@
 		intptr = &options->update_hostkeys;
 		goto parse_flag;
 
+	case oHostbasedKeyTypes:
+		charptr = &options->hostbased_key_types;
+		arg = strdelim(&s);
+		if (!arg || *arg == '\0')
+			fatal("%.200s line %d: Missing argument.",
+			    filename, linenum);
+		if (!sshkey_names_valid2(arg, 1))
+			fatal("%s line %d: Bad key types '%s'.",
+				filename, linenum, arg ? arg : "<NONE>");
+		if (*activep && *charptr == NULL)
+			*charptr = xstrdup(arg);
+		break;
+
 	case oDeprecated:
 		debug("%s line %d: Deprecated option \"%s\"",
 		    filename, linenum, keyword);
@@ -1660,6 +1674,7 @@
 	options->revoked_host_keys = NULL;
 	options->fingerprint_hash = -1;
 	options->update_hostkeys = -1;
+	options->hostbased_key_types = NULL;
 }
 
 /*
@@ -1841,6 +1856,8 @@
 		options->fingerprint_hash = SSH_FP_HASH_DEFAULT;
 	if (options->update_hostkeys == -1)
 		options->update_hostkeys = 1;
+	if (options->hostbased_key_types == NULL)
+		options->hostbased_key_types = xstrdup("*");
 
 #define CLEAR_ON_NONE(v) \
 	do { \
@@ -2281,6 +2298,7 @@
 	dump_cfg_string(oControlPath, o->control_path);
 	dump_cfg_string(oHostKeyAlgorithms, o->hostkeyalgorithms ? o->hostkeyalgorithms : KEX_DEFAULT_PK_ALG);
 	dump_cfg_string(oHostKeyAlias, o->host_key_alias);
+	dump_cfg_string(oHostbasedKeyTypes, o->hostbased_key_types);
 	dump_cfg_string(oKbdInteractiveDevices, o->kbd_interactive_devices);
 	dump_cfg_string(oKexAlgorithms, o->kex_algorithms ? o->kex_algorithms : KEX_CLIENT_KEX);
 	dump_cfg_string(oLocalCommand, o->local_command);
@@ -2289,9 +2307,10 @@
 	dump_cfg_string(oPKCS11Provider, o->pkcs11_provider);
 	dump_cfg_string(oPreferredAuthentications, o->preferred_authentications);
 	dump_cfg_string(oProxyCommand, o->proxy_command);
-	dump_cfg_string(oXAuthLocation, o->xauth_location);
 	dump_cfg_string(oRevokedHostKeys, o->revoked_host_keys);
+	dump_cfg_string(oXAuthLocation, o->xauth_location);
 
+	/* Forwards */
 	dump_cfg_forwards(oDynamicForward, o->num_local_forwards, o->local_forwards);
 	dump_cfg_forwards(oLocalForward, o->num_local_forwards, o->local_forwards);
 	dump_cfg_forwards(oRemoteForward, o->num_remote_forwards, o->remote_forwards);