[openssh-commits] [openssh] 09/14: upstream commit

git+noreply at mindrot.org git+noreply at mindrot.org
Tue Jan 23 16:50:05 AEDT 2018


This is an automated email from the git hooks/post-receive script.

djm pushed a commit to branch master
in repository openssh.

commit fc21ea97968264ad9bb86b13fedaaec8fd3bf97d
Author: djm at openbsd.org <djm at openbsd.org>
Date:   Tue Jan 23 05:06:25 2018 +0000

    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
---
 ssh.c | 88 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-------------
 1 file changed, 71 insertions(+), 17 deletions(-)

diff --git a/ssh.c b/ssh.c
index 86262543..ac85b2bb 100644
--- a/ssh.c
+++ b/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 at cs.hut.fi>
  * Copyright (c) 1995 Tatu Ylonen <ylo at 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;
 }
 
+/* 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.
  * Returns a canonical address string.
@@ -376,20 +410,10 @@ resolve_canonicalize(char **hostp, int port)
 	char *cp, *fullhost, newname[NI_MAXHOST];
 	struct addrinfo *addrs;
 
-	if (options.canonicalize_hostname == SSH_CANONICALISE_NO)
-		return NULL;
-
 	/*
-	 * Don't attempt to canonicalize names that will be interpreted by
-	 * a proxy unless the user specifically requests so.
+	 * Attempt to canonicalise addresses, regardless of
+	 * whether hostname canonicalisation was requested
 	 */
-	direct = option_clear_or_none(options.proxy_command) &&
-	    options.jump_host == NULL;
-	if (!direct &&
-	    options.canonicalize_hostname != SSH_CANONICALISE_ALWAYS)
-		return NULL;
-
-	/* Try numeric hostnames first */
 	if ((addrs = resolve_addr(*hostp, port,
 	    newname, sizeof(newname))) != NULL) {
 		debug2("%s: hostname %.100s is address", __func__, *hostp);
@@ -402,6 +426,30 @@ resolve_canonicalize(char **hostp, int port)
 		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)
+		return NULL;
+
+	/*
+	 * Don't attempt to canonicalize names that will be interpreted by
+	 * a proxy unless the user specifically requests so.
+	 */
+	direct = option_clear_or_none(options.proxy_command) &&
+	    options.jump_host == NULL;
+	if (!direct &&
+	    options.canonicalize_hostname != SSH_CANONICALISE_ALWAYS)
+		return NULL;
+
 	/* If domain name is anchored, then resolve it now */
 	if ((*hostp)[strlen(*hostp) - 1] == '.') {
 		debug3("%s: name is fully qualified", __func__);
@@ -514,7 +562,7 @@ main(int ac, char **av)
 {
 	struct ssh *ssh = NULL;
 	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 cname[NI_MAXHOST];
 	struct stat st;
@@ -1055,9 +1103,15 @@ main(int ac, char **av)
 		options.hostname = xstrdup(host);
 	}
 
-	/* If canonicalization requested then try to apply it */
-	lowercase(host);
-	if (options.canonicalize_hostname != SSH_CANONICALISE_NO)
+	/* Don't lowercase addresses, they will be explicitly canonicalised */
+	if ((was_addr = is_addr(host)) == 0)
+		lowercase(host);
+
+	/*
+	 * 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);
 
 	/*

-- 
To stop receiving notification emails like this one, please contact
djm at mindrot.org.


More information about the openssh-commits mailing list