diff options
-rw-r--r-- | ssh.c | 88 |
1 files changed, 71 insertions, 17 deletions
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: ssh.c,v 1.469 2017/11/01 00:04:15 djm Exp $ */ | 1 | /* $OpenBSD: ssh.c,v 1.470 2018/01/23 05:06:25 djm Exp $ */ |
2 | /* | 2 | /* |
3 | * Author: Tatu Ylonen <ylo@cs.hut.fi> | 3 | * Author: Tatu Ylonen <ylo@cs.hut.fi> |
4 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland | 4 | * 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) | |||
271 | return res; | 271 | return res; |
272 | } | 272 | } |
273 | 273 | ||
274 | /* Returns non-zero if name can only be an address and not a hostname */ | ||
275 | static int | ||
276 | is_addr_fast(const char *name) | ||
277 | { | ||
278 | return (strchr(name, '%') != NULL || strchr(name, ':') != NULL || | ||
279 | strspn(name, "0123456789.") == strlen(name)); | ||
280 | } | ||
281 | |||
282 | /* Returns non-zero if name represents a valid, single address */ | ||
283 | static int | ||
284 | is_addr(const char *name) | ||
285 | { | ||
286 | char strport[NI_MAXSERV]; | ||
287 | struct addrinfo hints, *res; | ||
288 | |||
289 | if (is_addr_fast(name)) | ||
290 | return 1; | ||
291 | |||
292 | snprintf(strport, sizeof strport, "%u", default_ssh_port()); | ||
293 | memset(&hints, 0, sizeof(hints)); | ||
294 | hints.ai_family = options.address_family == -1 ? | ||
295 | AF_UNSPEC : options.address_family; | ||
296 | hints.ai_socktype = SOCK_STREAM; | ||
297 | hints.ai_flags = AI_NUMERICHOST|AI_NUMERICSERV; | ||
298 | if (getaddrinfo(name, strport, &hints, &res) != 0) | ||
299 | return 0; | ||
300 | if (res == NULL || res->ai_next != NULL) { | ||
301 | freeaddrinfo(res); | ||
302 | return 0; | ||
303 | } | ||
304 | freeaddrinfo(res); | ||
305 | return 1; | ||
306 | } | ||
307 | |||
274 | /* | 308 | /* |
275 | * Attempt to resolve a numeric host address / port to a single address. | 309 | * Attempt to resolve a numeric host address / port to a single address. |
276 | * Returns a canonical address string. | 310 | * Returns a canonical address string. |
@@ -376,20 +410,10 @@ resolve_canonicalize(char **hostp, int port) | |||
376 | char *cp, *fullhost, newname[NI_MAXHOST]; | 410 | char *cp, *fullhost, newname[NI_MAXHOST]; |
377 | struct addrinfo *addrs; | 411 | struct addrinfo *addrs; |
378 | 412 | ||
379 | if (options.canonicalize_hostname == SSH_CANONICALISE_NO) | ||
380 | return NULL; | ||
381 | |||
382 | /* | 413 | /* |
383 | * Don't attempt to canonicalize names that will be interpreted by | 414 | * Attempt to canonicalise addresses, regardless of |
384 | * a proxy unless the user specifically requests so. | 415 | * whether hostname canonicalisation was requested |
385 | */ | 416 | */ |
386 | direct = option_clear_or_none(options.proxy_command) && | ||
387 | options.jump_host == NULL; | ||
388 | if (!direct && | ||
389 | options.canonicalize_hostname != SSH_CANONICALISE_ALWAYS) | ||
390 | return NULL; | ||
391 | |||
392 | /* Try numeric hostnames first */ | ||
393 | if ((addrs = resolve_addr(*hostp, port, | 417 | if ((addrs = resolve_addr(*hostp, port, |
394 | newname, sizeof(newname))) != NULL) { | 418 | newname, sizeof(newname))) != NULL) { |
395 | debug2("%s: hostname %.100s is address", __func__, *hostp); | 419 | debug2("%s: hostname %.100s is address", __func__, *hostp); |
@@ -402,6 +426,30 @@ resolve_canonicalize(char **hostp, int port) | |||
402 | return addrs; | 426 | return addrs; |
403 | } | 427 | } |
404 | 428 | ||
429 | /* | ||
430 | * If this looks like an address but didn't parse as one, it might | ||
431 | * be an address with an invalid interface scope. Skip further | ||
432 | * attempts at canonicalisation. | ||
433 | */ | ||
434 | if (is_addr_fast(*hostp)) { | ||
435 | debug("%s: hostname %.100s is an unrecognised address", | ||
436 | __func__, *hostp); | ||
437 | return NULL; | ||
438 | } | ||
439 | |||
440 | if (options.canonicalize_hostname == SSH_CANONICALISE_NO) | ||
441 | return NULL; | ||
442 | |||
443 | /* | ||
444 | * Don't attempt to canonicalize names that will be interpreted by | ||
445 | * a proxy unless the user specifically requests so. | ||
446 | */ | ||
447 | direct = option_clear_or_none(options.proxy_command) && | ||
448 | options.jump_host == NULL; | ||
449 | if (!direct && | ||
450 | options.canonicalize_hostname != SSH_CANONICALISE_ALWAYS) | ||
451 | return NULL; | ||
452 | |||
405 | /* If domain name is anchored, then resolve it now */ | 453 | /* If domain name is anchored, then resolve it now */ |
406 | if ((*hostp)[strlen(*hostp) - 1] == '.') { | 454 | if ((*hostp)[strlen(*hostp) - 1] == '.') { |
407 | debug3("%s: name is fully qualified", __func__); | 455 | debug3("%s: name is fully qualified", __func__); |
@@ -514,7 +562,7 @@ main(int ac, char **av) | |||
514 | { | 562 | { |
515 | struct ssh *ssh = NULL; | 563 | struct ssh *ssh = NULL; |
516 | int i, r, opt, exit_status, use_syslog, direct, timeout_ms; | 564 | int i, r, opt, exit_status, use_syslog, direct, timeout_ms; |
517 | int config_test = 0, opt_terminated = 0; | 565 | int was_addr, config_test = 0, opt_terminated = 0; |
518 | char *p, *cp, *line, *argv0, buf[PATH_MAX], *logfile; | 566 | char *p, *cp, *line, *argv0, buf[PATH_MAX], *logfile; |
519 | char cname[NI_MAXHOST]; | 567 | char cname[NI_MAXHOST]; |
520 | struct stat st; | 568 | struct stat st; |
@@ -1055,9 +1103,15 @@ main(int ac, char **av) | |||
1055 | options.hostname = xstrdup(host); | 1103 | options.hostname = xstrdup(host); |
1056 | } | 1104 | } |
1057 | 1105 | ||
1058 | /* If canonicalization requested then try to apply it */ | 1106 | /* Don't lowercase addresses, they will be explicitly canonicalised */ |
1059 | lowercase(host); | 1107 | if ((was_addr = is_addr(host)) == 0) |
1060 | if (options.canonicalize_hostname != SSH_CANONICALISE_NO) | 1108 | lowercase(host); |
1109 | |||
1110 | /* | ||
1111 | * Try to canonicalize if requested by configuration or the | ||
1112 | * hostname is an address. | ||
1113 | */ | ||
1114 | if (options.canonicalize_hostname != SSH_CANONICALISE_NO || was_addr) | ||
1061 | addrs = resolve_canonicalize(&host, options.port); | 1115 | addrs = resolve_canonicalize(&host, options.port); |
1062 | 1116 | ||
1063 | /* | 1117 | /* |