summaryrefslogtreecommitdiff
path: root/ssh.c
diff options
context:
space:
mode:
authordjm@openbsd.org <djm@openbsd.org>2014-10-08 22:20:25 +0000
committerDamien Miller <djm@mindrot.org>2014-10-13 11:41:48 +1100
commit957fbceb0f3166e41b76fdb54075ab3b9cc84cba (patch)
tree7c8bc1f0090201400383e51d84a7fda79995e513 /ssh.c
parent5c0dafd38bf66feeeb45fa0741a5baf5ad8039ba (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.c80
1 files changed, 61 insertions, 19 deletions
diff --git a/ssh.c b/ssh.c
index 26e9681b7..97f6e821d 100644
--- a/ssh.c
+++ b/ssh.c
@@ -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 */
386static void 386static void
387process_config_files(struct passwd *pw) 387process_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 */
414static void
415set_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)
414int 436int
415main(int ac, char **av) 437main(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)