upstream commit

Add "ssh-keyscan -c ..." flag to allow fetching
 certificates instead of plain keys; ok markus@

Upstream-ID: 0947e2177dba92339eced9e49d3c5bf7dda69f82
diff --git a/ssh-keyscan.c b/ssh-keyscan.c
index 7db0e10..0e5ca60 100644
--- a/ssh-keyscan.c
+++ b/ssh-keyscan.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ssh-keyscan.c,v 1.102 2015/10/24 22:56:19 djm Exp $ */
+/* $OpenBSD: ssh-keyscan.c,v 1.103 2015/11/08 22:30:20 djm Exp $ */
 /*
  * Copyright 1995, 1996 by David Mazieres <dm@lcs.mit.edu>.
  *
@@ -60,6 +60,7 @@
 #define KT_ECDSA	8
 #define KT_ED25519	16
 
+int get_cert = 0;
 int get_keytypes = KT_RSA|KT_ECDSA|KT_ED25519;
 
 int hash_hosts = 0;		/* Hash hostname on output */
@@ -267,11 +268,32 @@
 	int r;
 
 	enable_compat20();
-	myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] =
-	    c->c_keytype == KT_DSA ?  "ssh-dss" :
-	    (c->c_keytype == KT_RSA ? "ssh-rsa" :
-	    (c->c_keytype == KT_ED25519 ? "ssh-ed25519" :
-	    "ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521"));
+	switch (c->c_keytype) {
+	case KT_DSA:
+		myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = get_cert ?
+		    "ssh-dss-cert-v01@openssh.com" : "ssh-dss";
+		break;
+	case KT_RSA:
+		myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = get_cert ?
+		    "ssh-rsa-cert-v01@openssh.com" : "ssh-rsa";
+		break;
+	case KT_ED25519:
+		myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = get_cert ?
+		    "ssh-ed25519-cert-v01@openssh.com" : "ssh-ed25519";
+		break;
+	case KT_ECDSA:
+		myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = get_cert ?
+		    "ecdsa-sha2-nistp256-cert-v01@openssh.com,"
+		    "ecdsa-sha2-nistp384-cert-v01@openssh.com,"
+		    "ecdsa-sha2-nistp521-cert-v01@openssh.com" :
+		    "ecdsa-sha2-nistp256,"
+		    "ecdsa-sha2-nistp384,"
+		    "ecdsa-sha2-nistp521";
+		break;
+	default:
+		fatal("unknown key type %d", c->c_keytype);
+		break;
+	}
 	if ((r = kex_setup(c->c_ssh, myproposal)) != 0) {
 		free(c->c_ssh);
 		fprintf(stderr, "kex_setup: %s\n", ssh_err(r));
@@ -304,7 +326,8 @@
 		fatal("host_hash failed");
 
 	hostport = put_host_port(host, ssh_port);
-	fprintf(stdout, "%s ", hostport);
+	if (!get_cert)
+		fprintf(stdout, "%s ", hostport);
 	sshkey_write(key, stdout);
 	fputs("\n", stdout);
 	free(hostport);
@@ -318,7 +341,7 @@
 
 	if (key == NULL)
 		return;
-	if (!hash_hosts && ssh_port == SSH_DEFAULT_PORT) {
+	if (get_cert || (!hash_hosts && ssh_port == SSH_DEFAULT_PORT)) {
 		keyprint_one(hosts, key);
 		return;
 	}
@@ -384,6 +407,7 @@
 	if (fdcon[s].c_status)
 		fatal("conalloc: attempt to reuse fdno %d", s);
 
+	debug3("%s: oname %s kt %d", __func__, oname, keytype);
 	fdcon[s].c_fd = s;
 	fdcon[s].c_status = CS_CON;
 	fdcon[s].c_namebase = namebase;
@@ -654,7 +678,7 @@
 usage(void)
 {
 	fprintf(stderr,
-	    "usage: %s [-46Hv] [-f file] [-p port] [-T timeout] [-t type]\n"
+	    "usage: %s [-46Hcv] [-f file] [-p port] [-T timeout] [-t type]\n"
 	    "\t\t   [host | addrlist namelist] ...\n",
 	    __progname);
 	exit(1);
@@ -682,11 +706,14 @@
 	if (argc <= 1)
 		usage();
 
-	while ((opt = getopt(argc, argv, "Hv46p:T:t:f:")) != -1) {
+	while ((opt = getopt(argc, argv, "cHv46p:T:t:f:")) != -1) {
 		switch (opt) {
 		case 'H':
 			hash_hosts = 1;
 			break;
+		case 'c':
+			get_cert = 1;
+			break;
 		case 'p':
 			ssh_port = a2port(optarg);
 			if (ssh_port <= 0) {