summaryrefslogtreecommitdiffstats
path: root/clientloop.c
diff options
context:
space:
mode:
authordjm@openbsd.org <djm@openbsd.org>2020-01-25 00:21:08 +0000
committerDamien Miller <djm@mindrot.org>2020-01-25 11:35:56 +1100
commit7955633a554397bc24913cec9fd7285002935f7e (patch)
tree94808f0b095cf811cf322a432e9f20e84660b0f2 /clientloop.c
parente5a278a62ab49dffe96929fa8d8506c6928dba90 (diff)
upstream: allow UpdateKnownHosts=yes to function when multiple
known_hosts files are in use. When updating host keys, ssh will now search subsequent known_hosts files, but will add new/changed host keys to the first specified file only. bz#2738 ok markus@ OpenBSD-Commit-ID: 6ded6d878a03e57d5aa20bab9c31f92e929dbc6c
Diffstat (limited to 'clientloop.c')
-rw-r--r--clientloop.c57
1 files changed, 43 insertions, 14 deletions
diff --git a/clientloop.c b/clientloop.c
index d4c23d55..874e1286 100644
--- a/clientloop.c
+++ b/clientloop.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: clientloop.c,v 1.332 2020/01/23 07:10:22 dtucker Exp $ */
+/* $OpenBSD: clientloop.c,v 1.333 2020/01/25 00:21:08 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -1895,6 +1895,7 @@ update_known_hosts(struct hostkeys_update_ctx *ctx)
SYSLOG_LEVEL_INFO : SYSLOG_LEVEL_VERBOSE;
char *fp, *response;
size_t i;
+ struct stat sb;
for (i = 0; i < ctx->nkeys; i++) {
if (ctx->keys_seen[i] != 2)
@@ -1941,19 +1942,37 @@ update_known_hosts(struct hostkeys_update_ctx *ctx)
if (was_raw)
enter_raw_mode(1);
}
-
+ if (options.update_hostkeys == 0)
+ return;
/*
* Now that all the keys are verified, we can go ahead and replace
* them in known_hosts (assuming SSH_UPDATE_HOSTKEYS_ASK didn't
* cancel the operation).
*/
- if (options.update_hostkeys != 0 &&
- (r = hostfile_replace_entries(options.user_hostfiles[0],
- ctx->host_str, ctx->ip_str, ctx->keys, ctx->nkeys,
- options.hash_known_hosts, 0,
- options.fingerprint_hash)) != 0)
- error("%s: hostfile_replace_entries failed: %s",
- __func__, ssh_err(r));
+ for (i = 0; i < options.num_user_hostfiles; i++) {
+ /*
+ * NB. keys are only added to hostfiles[0], for the rest we
+ * just delete the hostname entries.
+ */
+ if (stat(options.user_hostfiles[i], &sb) != 0) {
+ if (errno == ENOENT) {
+ debug("%s: known hosts file %s does not exist",
+ __func__, strerror(errno));
+ } else {
+ error("%s: known hosts file %s inaccessible",
+ __func__, strerror(errno));
+ }
+ continue;
+ }
+ if ((r = hostfile_replace_entries(options.user_hostfiles[i],
+ ctx->host_str, ctx->ip_str,
+ i == 0 ? ctx->keys : NULL, i == 0 ? ctx->nkeys : 0,
+ options.hash_known_hosts, 0,
+ options.fingerprint_hash)) != 0) {
+ error("%s: hostfile_replace_entries failed for %s: %s",
+ __func__, options.user_hostfiles[i], ssh_err(r));
+ }
+ }
}
static void
@@ -2146,11 +2165,21 @@ client_input_hostkeys(struct ssh *ssh)
options.check_host_ip ? &ctx->ip_str : NULL);
/* Find which keys we already know about. */
- if ((r = hostkeys_foreach(options.user_hostfiles[0], hostkeys_find,
- ctx, ctx->host_str, ctx->ip_str,
- HKF_WANT_PARSE_KEY|HKF_WANT_MATCH)) != 0) {
- error("%s: hostkeys_foreach failed: %s", __func__, ssh_err(r));
- goto out;
+ for (i = 0; i < options.num_user_hostfiles; i++) {
+ debug("%s: searching %s for %s / %s", __func__,
+ options.user_hostfiles[i], ctx->host_str, ctx->ip_str);
+ if ((r = hostkeys_foreach(options.user_hostfiles[i],
+ hostkeys_find, ctx, ctx->host_str, ctx->ip_str,
+ HKF_WANT_PARSE_KEY|HKF_WANT_MATCH)) != 0) {
+ if (r == SSH_ERR_SYSTEM_ERROR && errno == ENOENT) {
+ error("%s: hostkeys file %s does not exist",
+ __func__, options.user_hostfiles[i]);
+ continue;
+ }
+ error("%s: hostkeys_foreach failed for %s: %s",
+ __func__, options.user_hostfiles[i], ssh_err(r));
+ goto out;
+ }
}
/* Figure out if we have any new keys to add */