mirror of
git://anongit.mindrot.org/openssh.git
synced 2025-04-08 18:44:46 +00:00
upstream commit
don't attempt to force hostnames that are addresses to lowercase, but instead canonicalise them through getnameinfo/getaddrinfo to remove ambiguities (e.g. ::0001 => ::1) before they are matched against known_hosts; bz#2763, ok dtucker@ OpenBSD-Commit-ID: ba0863ff087e61e5c65efdbe53be3cb92c9aefa0
This commit is contained in:
parent
d6364f6fb1
commit
fc21ea9796
88
ssh.c
88
ssh.c
@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: ssh.c,v 1.469 2017/11/01 00:04:15 djm Exp $ */
|
/* $OpenBSD: ssh.c,v 1.470 2018/01/23 05:06:25 djm Exp $ */
|
||||||
/*
|
/*
|
||||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||||
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||||
@ -271,6 +271,40 @@ resolve_host(const char *name, int port, int logerr, char *cname, size_t clen)
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Returns non-zero if name can only be an address and not a hostname */
|
||||||
|
static int
|
||||||
|
is_addr_fast(const char *name)
|
||||||
|
{
|
||||||
|
return (strchr(name, '%') != NULL || strchr(name, ':') != NULL ||
|
||||||
|
strspn(name, "0123456789.") == strlen(name));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Returns non-zero if name represents a valid, single address */
|
||||||
|
static int
|
||||||
|
is_addr(const char *name)
|
||||||
|
{
|
||||||
|
char strport[NI_MAXSERV];
|
||||||
|
struct addrinfo hints, *res;
|
||||||
|
|
||||||
|
if (is_addr_fast(name))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
snprintf(strport, sizeof strport, "%u", default_ssh_port());
|
||||||
|
memset(&hints, 0, sizeof(hints));
|
||||||
|
hints.ai_family = options.address_family == -1 ?
|
||||||
|
AF_UNSPEC : options.address_family;
|
||||||
|
hints.ai_socktype = SOCK_STREAM;
|
||||||
|
hints.ai_flags = AI_NUMERICHOST|AI_NUMERICSERV;
|
||||||
|
if (getaddrinfo(name, strport, &hints, &res) != 0)
|
||||||
|
return 0;
|
||||||
|
if (res == NULL || res->ai_next != NULL) {
|
||||||
|
freeaddrinfo(res);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
freeaddrinfo(res);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Attempt to resolve a numeric host address / port to a single address.
|
* Attempt to resolve a numeric host address / port to a single address.
|
||||||
* Returns a canonical address string.
|
* Returns a canonical address string.
|
||||||
@ -376,6 +410,33 @@ resolve_canonicalize(char **hostp, int port)
|
|||||||
char *cp, *fullhost, newname[NI_MAXHOST];
|
char *cp, *fullhost, newname[NI_MAXHOST];
|
||||||
struct addrinfo *addrs;
|
struct addrinfo *addrs;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Attempt to canonicalise addresses, regardless of
|
||||||
|
* whether hostname canonicalisation was requested
|
||||||
|
*/
|
||||||
|
if ((addrs = resolve_addr(*hostp, port,
|
||||||
|
newname, sizeof(newname))) != NULL) {
|
||||||
|
debug2("%s: hostname %.100s is address", __func__, *hostp);
|
||||||
|
if (strcasecmp(*hostp, newname) != 0) {
|
||||||
|
debug2("%s: canonicalised address \"%s\" => \"%s\"",
|
||||||
|
__func__, *hostp, newname);
|
||||||
|
free(*hostp);
|
||||||
|
*hostp = xstrdup(newname);
|
||||||
|
}
|
||||||
|
return addrs;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If this looks like an address but didn't parse as one, it might
|
||||||
|
* be an address with an invalid interface scope. Skip further
|
||||||
|
* attempts at canonicalisation.
|
||||||
|
*/
|
||||||
|
if (is_addr_fast(*hostp)) {
|
||||||
|
debug("%s: hostname %.100s is an unrecognised address",
|
||||||
|
__func__, *hostp);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
if (options.canonicalize_hostname == SSH_CANONICALISE_NO)
|
if (options.canonicalize_hostname == SSH_CANONICALISE_NO)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
@ -389,19 +450,6 @@ resolve_canonicalize(char **hostp, int port)
|
|||||||
options.canonicalize_hostname != SSH_CANONICALISE_ALWAYS)
|
options.canonicalize_hostname != SSH_CANONICALISE_ALWAYS)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
/* Try numeric hostnames first */
|
|
||||||
if ((addrs = resolve_addr(*hostp, port,
|
|
||||||
newname, sizeof(newname))) != NULL) {
|
|
||||||
debug2("%s: hostname %.100s is address", __func__, *hostp);
|
|
||||||
if (strcasecmp(*hostp, newname) != 0) {
|
|
||||||
debug2("%s: canonicalised address \"%s\" => \"%s\"",
|
|
||||||
__func__, *hostp, newname);
|
|
||||||
free(*hostp);
|
|
||||||
*hostp = xstrdup(newname);
|
|
||||||
}
|
|
||||||
return addrs;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If domain name is anchored, then resolve it now */
|
/* If domain name is anchored, then resolve it now */
|
||||||
if ((*hostp)[strlen(*hostp) - 1] == '.') {
|
if ((*hostp)[strlen(*hostp) - 1] == '.') {
|
||||||
debug3("%s: name is fully qualified", __func__);
|
debug3("%s: name is fully qualified", __func__);
|
||||||
@ -514,7 +562,7 @@ main(int ac, char **av)
|
|||||||
{
|
{
|
||||||
struct ssh *ssh = NULL;
|
struct ssh *ssh = NULL;
|
||||||
int i, r, opt, exit_status, use_syslog, direct, timeout_ms;
|
int i, r, opt, exit_status, use_syslog, direct, timeout_ms;
|
||||||
int config_test = 0, opt_terminated = 0;
|
int was_addr, config_test = 0, opt_terminated = 0;
|
||||||
char *p, *cp, *line, *argv0, buf[PATH_MAX], *logfile;
|
char *p, *cp, *line, *argv0, buf[PATH_MAX], *logfile;
|
||||||
char cname[NI_MAXHOST];
|
char cname[NI_MAXHOST];
|
||||||
struct stat st;
|
struct stat st;
|
||||||
@ -1055,9 +1103,15 @@ main(int ac, char **av)
|
|||||||
options.hostname = xstrdup(host);
|
options.hostname = xstrdup(host);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If canonicalization requested then try to apply it */
|
/* Don't lowercase addresses, they will be explicitly canonicalised */
|
||||||
|
if ((was_addr = is_addr(host)) == 0)
|
||||||
lowercase(host);
|
lowercase(host);
|
||||||
if (options.canonicalize_hostname != SSH_CANONICALISE_NO)
|
|
||||||
|
/*
|
||||||
|
* Try to canonicalize if requested by configuration or the
|
||||||
|
* hostname is an address.
|
||||||
|
*/
|
||||||
|
if (options.canonicalize_hostname != SSH_CANONICALISE_NO || was_addr)
|
||||||
addrs = resolve_canonicalize(&host, options.port);
|
addrs = resolve_canonicalize(&host, options.port);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
Loading…
Reference in New Issue
Block a user