]> git.ipfire.org Git - thirdparty/openssh-portable.git/commitdiff
upstream: allow UpdateKnownHosts=yes to function when multiple
authordjm@openbsd.org <djm@openbsd.org>
Sat, 25 Jan 2020 00:21:08 +0000 (00:21 +0000)
committerDamien Miller <djm@mindrot.org>
Sat, 25 Jan 2020 00:35:56 +0000 (11:35 +1100)
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

clientloop.c
hostfile.c
ssh.c

index d4c23d5541f9d959c82d2e17e4d039bfabebf441..874e1286d0aa3ed76e18842a04ed823dfcab4e9b 100644 (file)
@@ -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 */
index 96ab880d42cdaa13dc57c7c88293c34bef1a3399..4a0349a60a396793c508150d46b199802b9ea383 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: hostfile.c,v 1.76 2019/07/07 01:05:00 dtucker Exp $ */
+/* $OpenBSD: hostfile.c,v 1.77 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
@@ -566,6 +566,7 @@ hostfile_replace_entries(const char *filename, const char *host, const char *ip,
        /* Remove all entries for the specified host from the file */
        if ((r = hostkeys_foreach(filename, host_delete, &ctx, host, ip,
            HKF_WANT_PARSE_KEY)) != 0) {
+               oerrno = errno;
                error("%s: hostkeys_foreach failed: %s", __func__, ssh_err(r));
                goto fail;
        }
diff --git a/ssh.c b/ssh.c
index 8931ecf81cf0c750ade35efebf9b7649c681e052..4998ebc16eeac39ebaade3babf09aaa6af7c7b7a 100644 (file)
--- a/ssh.c
+++ b/ssh.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ssh.c,v 1.514 2020/01/25 00:03:36 djm Exp $ */
+/* $OpenBSD: ssh.c,v 1.515 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
@@ -1248,7 +1248,7 @@ main(int ac, char **av)
            strcmp(options.proxy_command, "-") == 0 &&
            options.proxy_use_fdpass)
                fatal("ProxyCommand=- and ProxyUseFDPass are incompatible");
-       if (options.control_persist &&
+       if (options.control_persist && options.control_path != NULL &&
            options.update_hostkeys == SSH_UPDATE_HOSTKEYS_ASK) {
                debug("UpdateHostKeys=ask is incompatible with ControlPersist; "
                    "disabling");