diff options
author | djm@openbsd.org <djm@openbsd.org> | 2020-01-25 00:21:08 +0000 |
---|---|---|
committer | Damien Miller <djm@mindrot.org> | 2020-01-25 11:35:56 +1100 |
commit | 7955633a554397bc24913cec9fd7285002935f7e (patch) | |
tree | 94808f0b095cf811cf322a432e9f20e84660b0f2 /clientloop.c | |
parent | e5a278a62ab49dffe96929fa8d8506c6928dba90 (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.c | 57 |
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 */ |