summaryrefslogtreecommitdiff
path: root/usr.bin/ssh/sshd.c
diff options
context:
space:
mode:
authorDamien Miller <djm@cvs.openbsd.org>2015-01-26 03:04:47 +0000
committerDamien Miller <djm@cvs.openbsd.org>2015-01-26 03:04:47 +0000
commiteb39409bcc73a02ed00ce4a050ca400115a85aca (patch)
tree3417642a1daec6e71a2156999d8626d947d63875 /usr.bin/ssh/sshd.c
parentec70fe89ea2c7355199e5eda04e830bb613137cb (diff)
Host key rotation support.
Add a hostkeys@openssh.com protocol extension (global request) for a server to inform a client of all its available host key after authentication has completed. The client may record the keys in known_hosts, allowing it to upgrade to better host key algorithms and a server to gracefully rotate its keys. The client side of this is controlled by a UpdateHostkeys config option (default on). ok markus@
Diffstat (limited to 'usr.bin/ssh/sshd.c')
-rw-r--r--usr.bin/ssh/sshd.c44
1 files changed, 43 insertions, 1 deletions
diff --git a/usr.bin/ssh/sshd.c b/usr.bin/ssh/sshd.c
index da6b133aff6..b7596e4bae3 100644
--- a/usr.bin/ssh/sshd.c
+++ b/usr.bin/ssh/sshd.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: sshd.c,v 1.438 2015/01/20 23:14:00 deraadt Exp $ */
+/* $OpenBSD: sshd.c,v 1.439 2015/01/26 03:04:46 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -874,6 +874,42 @@ get_hostkey_index(Key *key, struct ssh *ssh)
return (-1);
}
+/* Inform the client of all hostkeys */
+static void
+notify_hostkeys(struct ssh *ssh)
+{
+ struct sshbuf *buf;
+ struct sshkey *key;
+ int i, nkeys, r;
+ char *fp;
+
+ if ((buf = sshbuf_new()) == NULL)
+ fatal("%s: sshbuf_new", __func__);
+ for (i = nkeys = 0; i < options.num_host_key_files; i++) {
+ key = get_hostkey_public_by_index(i, ssh);
+ if (key == NULL || key->type == KEY_UNSPEC ||
+ key->type == KEY_RSA1 || sshkey_is_cert(key))
+ continue;
+ fp = sshkey_fingerprint(key, options.fingerprint_hash,
+ SSH_FP_DEFAULT);
+ debug3("%s: key %d: %s %s", __func__, i,
+ sshkey_ssh_name(key), fp);
+ free(fp);
+ if ((r = sshkey_puts(key, buf)) != 0)
+ fatal("%s: couldn't put hostkey %d: %s",
+ __func__, i, ssh_err(r));
+ 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();
+}
+
/*
* returns 1 if connection should be dropped, 0 otherwise.
* dropping starts at connection #max_startups_begin with a probability
@@ -1608,6 +1644,8 @@ main(int ac, char **av)
continue;
key = key_load_private(options.host_key_files[i], "", NULL);
pubkey = key_load_public(options.host_key_files[i], NULL);
+ if (pubkey == NULL && key != NULL)
+ pubkey = key_demote(key);
sensitive_data.host_keys[i] = key;
sensitive_data.host_pubkeys[i] = pubkey;
@@ -2021,6 +2059,10 @@ main(int ac, char **av)
packet_set_timeout(options.client_alive_interval,
options.client_alive_count_max);
+ /* Try to send all our hostkeys to the client */
+ if (compat20)
+ notify_hostkeys(active_state);
+
/* Start session. */
do_authenticated(authctxt);