upstream commit

Revise hostkeys@openssh.com hostkey learning extension.

The client will not ask the server to prove ownership of the private
halves of any hitherto-unseen hostkeys it offers to the client.

Allow UpdateHostKeys option to take an 'ask' argument to let the
user manually review keys offered.

ok markus@
diff --git a/sshd.c b/sshd.c
index 4282bdc..aaa63d4 100644
--- a/sshd.c
+++ b/sshd.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: sshd.c,v 1.441 2015/01/31 20:30:05 djm Exp $ */
+/* $OpenBSD: sshd.c,v 1.442 2015/02/16 22:13:32 djm Exp $ */
 /*
  * Author: Tatu Ylonen <ylo@cs.hut.fi>
  * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -894,18 +894,25 @@
 }
 
 int
-get_hostkey_index(Key *key, struct ssh *ssh)
+get_hostkey_index(Key *key, int compare, struct ssh *ssh)
 {
 	int i;
 
 	for (i = 0; i < options.num_host_key_files; i++) {
 		if (key_is_cert(key)) {
-			if (key == sensitive_data.host_certificates[i])
+			if (key == sensitive_data.host_certificates[i] ||
+			    (compare && sensitive_data.host_certificates[i] &&
+			    sshkey_equal(key,
+			    sensitive_data.host_certificates[i])))
 				return (i);
 		} else {
-			if (key == sensitive_data.host_keys[i])
+			if (key == sensitive_data.host_keys[i] ||
+			    (compare && sensitive_data.host_keys[i] &&
+			    sshkey_equal(key, sensitive_data.host_keys[i])))
 				return (i);
-			if (key == sensitive_data.host_pubkeys[i])
+			if (key == sensitive_data.host_pubkeys[i] ||
+			    (compare && sensitive_data.host_pubkeys[i] &&
+			    sshkey_equal(key, sensitive_data.host_pubkeys[i])))
 				return (i);
 		}
 	}
@@ -933,19 +940,23 @@
 		debug3("%s: key %d: %s %s", __func__, i,
 		    sshkey_ssh_name(key), fp);
 		free(fp);
-		if ((r = sshkey_puts(key, buf)) != 0)
+		if (nkeys == 0) {
+			packet_start(SSH2_MSG_GLOBAL_REQUEST);
+			packet_put_cstring("hostkeys@openssh.com");
+			packet_put_char(0); /* want-reply */
+		}
+		sshbuf_reset(buf);
+		if ((r = sshkey_putb(key, buf)) != 0)
 			fatal("%s: couldn't put hostkey %d: %s",
 			    __func__, i, ssh_err(r));
+		packet_put_string(sshbuf_ptr(buf), sshbuf_len(buf));
 		nkeys++;
 	}
+	debug3("%s: sent %d hostkeys", __func__, nkeys);
 	if (nkeys == 0)
 		fatal("%s: no hostkeys", __func__);
-	debug3("%s: send %d hostkeys", __func__, nkeys);
-	packet_start(SSH2_MSG_GLOBAL_REQUEST);
-	packet_put_cstring("hostkeys@openssh.com");
-	packet_put_char(0); /* want-reply */
-	packet_put_string(sshbuf_ptr(buf), sshbuf_len(buf));
 	packet_send();
+	sshbuf_free(buf);
 }
 
 /*
@@ -2484,7 +2495,7 @@
 
 int
 sshd_hostkey_sign(Key *privkey, Key *pubkey, u_char **signature, size_t *slen,
-    u_char *data, size_t dlen, u_int flag)
+    const u_char *data, size_t dlen, u_int flag)
 {
 	int r;
 	u_int xxx_slen, xxx_dlen = dlen;