summaryrefslogtreecommitdiff
path: root/clientloop.c
diff options
context:
space:
mode:
authordjm@openbsd.org <djm@openbsd.org>2020-10-11 22:12:44 +0000
committerDamien Miller <djm@mindrot.org>2020-10-12 11:22:55 +1100
commitaf5941ae9b013aac12585e84c4cf494f3728982f (patch)
tree878f91b3701e0c061d90979e328a6dda8ee226d5 /clientloop.c
parent6247812c76f70b2245f3c23f5074665b3d436cae (diff)
downloadopenssh-git-af5941ae9b013aac12585e84c4cf494f3728982f.tar.gz
upstream: UpdateHostkeys: better detect manual host entries
Disable UpdateHostkeys if the known_hosts line has more than two entries in the pattern-list. ssh(1) only writes "host" or "host,ip" lines so anything else was added by a different tool or by a human. ok markus@ OpenBSD-Commit-ID: e434828191fb5f3877d4887c218682825aa59820
Diffstat (limited to 'clientloop.c')
-rw-r--r--clientloop.c54
1 files changed, 37 insertions, 17 deletions
diff --git a/clientloop.c b/clientloop.c
index f3014b8d..9daec13c 100644
--- a/clientloop.c
+++ b/clientloop.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: clientloop.c,v 1.349 2020/10/08 01:15:16 djm Exp $ */
+/* $OpenBSD: clientloop.c,v 1.350 2020/10/11 22:12:44 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -1830,7 +1830,7 @@ struct hostkeys_update_ctx {
size_t nold;
/* Various special cases. */
- int wildcard_hostspec; /* saw wildcard or pattern-list host name */
+ int complex_hostspec; /* wildcard or manual pattern-list host name */
int ca_available; /* saw CA key for this host */
};
@@ -1853,6 +1853,29 @@ hostkeys_update_ctx_free(struct hostkeys_update_ctx *ctx)
free(ctx);
}
+/*
+ * Returns non-zero if a known_hosts hostname list is not of a form that
+ * can be handled by UpdateHostkeys. These include wildcard hostnames and
+ * hostnames lists that do not follow the form host[,ip].
+ */
+static int
+hostspec_is_complex(const char *hosts)
+{
+ char *cp;
+
+ /* wildcard */
+ if (strchr(hosts, '*') != NULL || strchr(hosts, '?') != NULL)
+ return 1;
+ /* single host/ip = ok */
+ if ((cp = strchr(hosts, ',')) == NULL)
+ return 0;
+ /* more than two entries on the line */
+ if (strchr(cp + 1, ',') != NULL)
+ return 1;
+ /* XXX maybe parse cp+1 and ensure it is an IP? */
+ return 0;
+}
+
static int
hostkeys_find(struct hostkey_foreach_line *l, void *_ctx)
{
@@ -1860,24 +1883,21 @@ hostkeys_find(struct hostkey_foreach_line *l, void *_ctx)
size_t i;
struct sshkey **tmp;
- if (l->status != HKF_STATUS_MATCHED || l->key == NULL)
+ if (l->status != HKF_STATUS_MATCHED || l->key == NULL ||
+ l->marker != MRK_NONE)
return 0;
- if (l->marker == MRK_REVOKE)
- return 0;
- if (l->marker == MRK_CA) {
- ctx->ca_available = 1;
+ /*
+ * UpdateHostkeys is skipped for wildcard host names and hostnames
+ * that contain more than two entries (ssh never writes these).
+ */
+ if (hostspec_is_complex(l->hosts)) {
+ debug3("%s: hostkeys file %s:%ld complex host specification",
+ __func__, l->path, l->linenum);
+ ctx->complex_hostspec = 1;
return 0;
}
- /* UpdateHostkeys is skipped for wildcard host names */
- if (strchr(l->hosts, '*') != NULL ||
- strchr(l->hosts, '?') != NULL) {
- debug3("%s: hostkeys file %s:%ld contains wildcard", __func__,
- l->path, l->linenum);
- ctx->wildcard_hostspec = 1;
- }
-
/* Mark off keys we've already seen for this host */
for (i = 0; i < ctx->nkeys; i++) {
if (sshkey_equal(l->key, ctx->keys[i])) {
@@ -2223,8 +2243,8 @@ client_input_hostkeys(struct ssh *ssh)
debug3("%s: %zu keys from server: %zu new, %zu retained. %zu to remove",
__func__, ctx->nkeys, ctx->nnew, ctx->nkeys - ctx->nnew, ctx->nold);
- if (ctx->wildcard_hostspec && (ctx->nnew != 0 || ctx->nold != 0)) {
- debug("%s: wildcard known hosts name found, "
+ if (ctx->complex_hostspec && (ctx->nnew != 0 || ctx->nold != 0)) {
+ debug("%s: manual list or wildcard host pattern found, "
"skipping UserKnownHostsFile update", __func__);
goto out;
} else if (ctx->nnew == 0 && ctx->nold != 0) {