version 1.349, 2020/10/08 01:15:16 |
version 1.350, 2020/10/11 22:12:44 |
|
|
size_t nold; |
size_t nold; |
|
|
/* Various special cases. */ |
/* 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 */ |
int ca_available; /* saw CA key for this host */ |
}; |
}; |
|
|
|
|
free(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 |
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) |
hostkeys_find(struct hostkey_foreach_line *l, void *_ctx) |
{ |
{ |
struct hostkeys_update_ctx *ctx = (struct hostkeys_update_ctx *)_ctx; |
struct hostkeys_update_ctx *ctx = (struct hostkeys_update_ctx *)_ctx; |
size_t i; |
size_t i; |
struct sshkey **tmp; |
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; |
return 0; |
|
|
if (l->marker == MRK_REVOKE) |
/* |
|
* 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; |
return 0; |
if (l->marker == MRK_CA) { |
|
ctx->ca_available = 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 */ |
/* Mark off keys we've already seen for this host */ |
for (i = 0; i < ctx->nkeys; i++) { |
for (i = 0; i < ctx->nkeys; i++) { |
if (sshkey_equal(l->key, ctx->keys[i])) { |
if (sshkey_equal(l->key, ctx->keys[i])) { |
|
|
debug3("%s: %zu keys from server: %zu new, %zu retained. %zu to remove", |
debug3("%s: %zu keys from server: %zu new, %zu retained. %zu to remove", |
__func__, ctx->nkeys, ctx->nnew, ctx->nkeys - ctx->nnew, ctx->nold); |
__func__, ctx->nkeys, ctx->nnew, ctx->nkeys - ctx->nnew, ctx->nold); |
|
|
if (ctx->wildcard_hostspec && (ctx->nnew != 0 || ctx->nold != 0)) { |
if (ctx->complex_hostspec && (ctx->nnew != 0 || ctx->nold != 0)) { |
debug("%s: wildcard known hosts name found, " |
debug("%s: manual list or wildcard host pattern found, " |
"skipping UserKnownHostsFile update", __func__); |
"skipping UserKnownHostsFile update", __func__); |
goto out; |
goto out; |
} else if (ctx->nnew == 0 && ctx->nold != 0) { |
} else if (ctx->nnew == 0 && ctx->nold != 0) { |