diff options
author | djm@openbsd.org <djm@openbsd.org> | 2014-10-08 22:20:25 +0000 |
---|---|---|
committer | Damien Miller <djm@mindrot.org> | 2014-10-13 11:41:48 +1100 |
commit | 957fbceb0f3166e41b76fdb54075ab3b9cc84cba (patch) | |
tree | 7c8bc1f0090201400383e51d84a7fda79995e513 /ssh.c | |
parent | 5c0dafd38bf66feeeb45fa0741a5baf5ad8039ba (diff) |
upstream commit
Tweak config reparsing with host canonicalisation
Make the second pass through the config files always run when
hostname canonicalisation is enabled.
Add a "Match canonical" criteria that allows ssh_config Match
blocks to trigger only in the second config pass.
Add a -G option to ssh that causes it to parse its configuration
and dump the result to stdout, similar to "sshd -T"
Allow ssh_config Port options set in the second config parse
phase to be applied (they were being ignored).
bz#2267 bz#2286; ok markus
Diffstat (limited to 'ssh.c')
-rw-r--r-- | ssh.c | 80 |
1 files changed, 61 insertions, 19 deletions
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: ssh.c,v 1.407 2014/07/17 07:22:19 djm Exp $ */ | 1 | /* $OpenBSD: ssh.c,v 1.408 2014/10/08 22:20: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 |
@@ -384,27 +384,49 @@ resolve_canonicalize(char **hostp, int port) | |||
384 | * file if the user specifies a config file on the command line. | 384 | * file if the user specifies a config file on the command line. |
385 | */ | 385 | */ |
386 | static void | 386 | static void |
387 | process_config_files(struct passwd *pw) | 387 | process_config_files(const char *host_arg, struct passwd *pw, int post_canon) |
388 | { | 388 | { |
389 | char buf[MAXPATHLEN]; | 389 | char buf[MAXPATHLEN]; |
390 | int r; | 390 | int r; |
391 | 391 | ||
392 | if (config != NULL) { | 392 | if (config != NULL) { |
393 | if (strcasecmp(config, "none") != 0 && | 393 | if (strcasecmp(config, "none") != 0 && |
394 | !read_config_file(config, pw, host, &options, | 394 | !read_config_file(config, pw, host, host_arg, &options, |
395 | SSHCONF_USERCONF)) | 395 | SSHCONF_USERCONF | (post_canon ? SSHCONF_POSTCANON : 0))) |
396 | fatal("Can't open user config file %.100s: " | 396 | fatal("Can't open user config file %.100s: " |
397 | "%.100s", config, strerror(errno)); | 397 | "%.100s", config, strerror(errno)); |
398 | } else { | 398 | } else { |
399 | r = snprintf(buf, sizeof buf, "%s/%s", pw->pw_dir, | 399 | r = snprintf(buf, sizeof buf, "%s/%s", pw->pw_dir, |
400 | _PATH_SSH_USER_CONFFILE); | 400 | _PATH_SSH_USER_CONFFILE); |
401 | if (r > 0 && (size_t)r < sizeof(buf)) | 401 | if (r > 0 && (size_t)r < sizeof(buf)) |
402 | (void)read_config_file(buf, pw, host, &options, | 402 | (void)read_config_file(buf, pw, host, host_arg, |
403 | SSHCONF_CHECKPERM|SSHCONF_USERCONF); | 403 | &options, SSHCONF_CHECKPERM | SSHCONF_USERCONF | |
404 | (post_canon ? SSHCONF_POSTCANON : 0)); | ||
404 | 405 | ||
405 | /* Read systemwide configuration file after user config. */ | 406 | /* Read systemwide configuration file after user config. */ |
406 | (void)read_config_file(_PATH_HOST_CONFIG_FILE, pw, host, | 407 | (void)read_config_file(_PATH_HOST_CONFIG_FILE, pw, |
407 | &options, 0); | 408 | host, host_arg, &options, |
409 | post_canon ? SSHCONF_POSTCANON : 0); | ||
410 | } | ||
411 | } | ||
412 | |||
413 | /* Rewrite the port number in an addrinfo list of addresses */ | ||
414 | static void | ||
415 | set_addrinfo_port(struct addrinfo *addrs, int port) | ||
416 | { | ||
417 | struct addrinfo *addr; | ||
418 | |||
419 | for (addr = addrs; addr != NULL; addr = addr->ai_next) { | ||
420 | switch (addr->ai_family) { | ||
421 | case AF_INET: | ||
422 | ((struct sockaddr_in *)addr->ai_addr)-> | ||
423 | sin_port = htons(port); | ||
424 | break; | ||
425 | case AF_INET6: | ||
426 | ((struct sockaddr_in6 *)addr->ai_addr)-> | ||
427 | sin6_port = htons(port); | ||
428 | break; | ||
429 | } | ||
408 | } | 430 | } |
409 | } | 431 | } |
410 | 432 | ||
@@ -414,7 +436,7 @@ process_config_files(struct passwd *pw) | |||
414 | int | 436 | int |
415 | main(int ac, char **av) | 437 | main(int ac, char **av) |
416 | { | 438 | { |
417 | int i, r, opt, exit_status, use_syslog; | 439 | int i, r, opt, exit_status, use_syslog, config_test = 0; |
418 | char *p, *cp, *line, *argv0, buf[MAXPATHLEN], *host_arg, *logfile; | 440 | char *p, *cp, *line, *argv0, buf[MAXPATHLEN], *host_arg, *logfile; |
419 | char thishost[NI_MAXHOST], shorthost[NI_MAXHOST], portstr[NI_MAXSERV]; | 441 | char thishost[NI_MAXHOST], shorthost[NI_MAXHOST], portstr[NI_MAXSERV]; |
420 | char cname[NI_MAXHOST]; | 442 | char cname[NI_MAXHOST]; |
@@ -507,7 +529,7 @@ main(int ac, char **av) | |||
507 | 529 | ||
508 | again: | 530 | again: |
509 | while ((opt = getopt(ac, av, "1246ab:c:e:fgi:kl:m:no:p:qstvx" | 531 | while ((opt = getopt(ac, av, "1246ab:c:e:fgi:kl:m:no:p:qstvx" |
510 | "ACD:E:F:I:KL:MNO:PQ:R:S:TVw:W:XYy")) != -1) { | 532 | "ACD:E:F:GI:KL:MNO:PQ:R:S:TVw:W:XYy")) != -1) { |
511 | switch (opt) { | 533 | switch (opt) { |
512 | case '1': | 534 | case '1': |
513 | options.protocol = SSH_PROTO_1; | 535 | options.protocol = SSH_PROTO_1; |
@@ -540,6 +562,9 @@ main(int ac, char **av) | |||
540 | case 'E': | 562 | case 'E': |
541 | logfile = xstrdup(optarg); | 563 | logfile = xstrdup(optarg); |
542 | break; | 564 | break; |
565 | case 'G': | ||
566 | config_test = 1; | ||
567 | break; | ||
543 | case 'Y': | 568 | case 'Y': |
544 | options.forward_x11 = 1; | 569 | options.forward_x11 = 1; |
545 | options.forward_x11_trusted = 1; | 570 | options.forward_x11_trusted = 1; |
@@ -788,9 +813,9 @@ main(int ac, char **av) | |||
788 | break; | 813 | break; |
789 | case 'o': | 814 | case 'o': |
790 | line = xstrdup(optarg); | 815 | line = xstrdup(optarg); |
791 | if (process_config_line(&options, pw, host ? host : "", | 816 | if (process_config_line(&options, pw, |
792 | line, "command-line", 0, NULL, SSHCONF_USERCONF) | 817 | host ? host : "", host ? host : "", line, |
793 | != 0) | 818 | "command-line", 0, NULL, SSHCONF_USERCONF) != 0) |
794 | exit(255); | 819 | exit(255); |
795 | free(line); | 820 | free(line); |
796 | break; | 821 | break; |
@@ -899,7 +924,7 @@ main(int ac, char **av) | |||
899 | ); | 924 | ); |
900 | 925 | ||
901 | /* Parse the configuration files */ | 926 | /* Parse the configuration files */ |
902 | process_config_files(pw); | 927 | process_config_files(host_arg, pw, 0); |
903 | 928 | ||
904 | /* Hostname canonicalisation needs a few options filled. */ | 929 | /* Hostname canonicalisation needs a few options filled. */ |
905 | fill_default_options_for_canonicalization(&options); | 930 | fill_default_options_for_canonicalization(&options); |
@@ -911,6 +936,8 @@ main(int ac, char **av) | |||
911 | "h", host, (char *)NULL); | 936 | "h", host, (char *)NULL); |
912 | free(host); | 937 | free(host); |
913 | host = cp; | 938 | host = cp; |
939 | free(options.hostname); | ||
940 | options.hostname = xstrdup(host); | ||
914 | } | 941 | } |
915 | 942 | ||
916 | /* If canonicalization requested then try to apply it */ | 943 | /* If canonicalization requested then try to apply it */ |
@@ -945,12 +972,22 @@ main(int ac, char **av) | |||
945 | } | 972 | } |
946 | 973 | ||
947 | /* | 974 | /* |
948 | * If the target hostname has changed as a result of canonicalisation | 975 | * If canonicalisation is enabled then re-parse the configuration |
949 | * then re-parse the configuration files as new stanzas may match. | 976 | * files as new stanzas may match. |
950 | */ | 977 | */ |
951 | if (strcasecmp(host_arg, host) != 0) { | 978 | if (options.canonicalize_hostname != 0) { |
952 | debug("Hostname has changed; re-reading configuration"); | 979 | debug("Re-reading configuration after hostname " |
953 | process_config_files(pw); | 980 | "canonicalisation"); |
981 | free(options.hostname); | ||
982 | options.hostname = xstrdup(host); | ||
983 | process_config_files(host_arg, pw, 1); | ||
984 | /* | ||
985 | * Address resolution happens early with canonicalisation | ||
986 | * enabled and the port number may have changed since, so | ||
987 | * reset it in address list | ||
988 | */ | ||
989 | if (addrs != NULL && options.port > 0) | ||
990 | set_addrinfo_port(addrs, options.port); | ||
954 | } | 991 | } |
955 | 992 | ||
956 | /* Fill configuration defaults. */ | 993 | /* Fill configuration defaults. */ |
@@ -1052,6 +1089,11 @@ main(int ac, char **av) | |||
1052 | } | 1089 | } |
1053 | free(conn_hash_hex); | 1090 | free(conn_hash_hex); |
1054 | 1091 | ||
1092 | if (config_test) { | ||
1093 | dump_client_config(&options, host); | ||
1094 | exit(0); | ||
1095 | } | ||
1096 | |||
1055 | if (muxclient_command != 0 && options.control_path == NULL) | 1097 | if (muxclient_command != 0 && options.control_path == NULL) |
1056 | fatal("No ControlPath specified for \"-O\" command"); | 1098 | fatal("No ControlPath specified for \"-O\" command"); |
1057 | if (options.control_path != NULL) | 1099 | if (options.control_path != NULL) |