diff options
author | Damien Miller <djm@mindrot.org> | 2014-02-24 15:57:55 +1100 |
---|---|---|
committer | Damien Miller <djm@mindrot.org> | 2014-02-24 15:57:55 +1100 |
commit | 13f97b2286142fd0b8eab94e4ce84fe124eeb752 (patch) | |
tree | b332b16a032b4670b60db1261b6dac48e059d916 | |
parent | bee3a234f3d1ad4244952bcff1b4b7c525330dc2 (diff) |
- djm@cvs.openbsd.org 2014/02/23 20:11:36
[readconf.c readconf.h ssh.c ssh_config.5]
reparse ssh_config and ~/.ssh/config if hostname canonicalisation changes
the hostname. This allows users to write configurations that always
refer to canonical hostnames, e.g.
CanonicalizeHostname yes
CanonicalDomains int.example.org example.org
CanonicalizeFallbackLocal no
Host *.int.example.org
Compression off
Host *.example.org
User djm
ok markus@
-rw-r--r-- | ChangeLog | 16 | ||||
-rw-r--r-- | readconf.c | 27 | ||||
-rw-r--r-- | readconf.h | 4 | ||||
-rw-r--r-- | ssh.c | 150 | ||||
-rw-r--r-- | ssh_config.5 | 10 |
5 files changed, 145 insertions, 62 deletions
@@ -16,6 +16,22 @@ | |||
16 | [ssh-ed25519.c] | 16 | [ssh-ed25519.c] |
17 | check for unsigned overflow; not reachable in OpenSSH but others might | 17 | check for unsigned overflow; not reachable in OpenSSH but others might |
18 | copy our code... | 18 | copy our code... |
19 | - djm@cvs.openbsd.org 2014/02/23 20:11:36 | ||
20 | [readconf.c readconf.h ssh.c ssh_config.5] | ||
21 | reparse ssh_config and ~/.ssh/config if hostname canonicalisation changes | ||
22 | the hostname. This allows users to write configurations that always | ||
23 | refer to canonical hostnames, e.g. | ||
24 | |||
25 | CanonicalizeHostname yes | ||
26 | CanonicalDomains int.example.org example.org | ||
27 | CanonicalizeFallbackLocal no | ||
28 | |||
29 | Host *.int.example.org | ||
30 | Compression off | ||
31 | Host *.example.org | ||
32 | User djm | ||
33 | |||
34 | ok markus@ | ||
19 | 35 | ||
20 | 20140213 | 36 | 20140213 |
21 | - (dtucker) [configure.ac openbsd-compat/openssl-compat.{c,h}] Add compat | 37 | - (dtucker) [configure.ac openbsd-compat/openssl-compat.{c,h}] Add compat |
diff --git a/readconf.c b/readconf.c index 94e645908..dc884c9b1 100644 --- a/readconf.c +++ b/readconf.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: readconf.c,v 1.217 2014/02/22 01:32:19 djm Exp $ */ | 1 | /* $OpenBSD: readconf.c,v 1.218 2014/02/23 20:11:36 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 |
@@ -1467,6 +1467,13 @@ read_config_file(const char *filename, struct passwd *pw, const char *host, | |||
1467 | return 1; | 1467 | return 1; |
1468 | } | 1468 | } |
1469 | 1469 | ||
1470 | /* Returns 1 if a string option is unset or set to "none" or 0 otherwise. */ | ||
1471 | int | ||
1472 | option_clear_or_none(const char *o) | ||
1473 | { | ||
1474 | return o == NULL || strcasecmp(o, "none") == 0; | ||
1475 | } | ||
1476 | |||
1470 | /* | 1477 | /* |
1471 | * Initializes options to special values that indicate that they have not yet | 1478 | * Initializes options to special values that indicate that they have not yet |
1472 | * been set. Read_config_file will only set options with this value. Options | 1479 | * been set. Read_config_file will only set options with this value. Options |
@@ -1564,10 +1571,24 @@ initialize_options(Options * options) | |||
1564 | } | 1571 | } |
1565 | 1572 | ||
1566 | /* | 1573 | /* |
1574 | * A petite version of fill_default_options() that just fills the options | ||
1575 | * needed for hostname canonicalization to proceed. | ||
1576 | */ | ||
1577 | void | ||
1578 | fill_default_options_for_canonicalization(Options *options) | ||
1579 | { | ||
1580 | if (options->canonicalize_max_dots == -1) | ||
1581 | options->canonicalize_max_dots = 1; | ||
1582 | if (options->canonicalize_fallback_local == -1) | ||
1583 | options->canonicalize_fallback_local = 1; | ||
1584 | if (options->canonicalize_hostname == -1) | ||
1585 | options->canonicalize_hostname = SSH_CANONICALISE_NO; | ||
1586 | } | ||
1587 | |||
1588 | /* | ||
1567 | * Called after processing other sources of option data, this fills those | 1589 | * Called after processing other sources of option data, this fills those |
1568 | * options for which no value has been specified with their default values. | 1590 | * options for which no value has been specified with their default values. |
1569 | */ | 1591 | */ |
1570 | |||
1571 | void | 1592 | void |
1572 | fill_default_options(Options * options) | 1593 | fill_default_options(Options * options) |
1573 | { | 1594 | { |
@@ -1722,7 +1743,7 @@ fill_default_options(Options * options) | |||
1722 | options->canonicalize_hostname = SSH_CANONICALISE_NO; | 1743 | options->canonicalize_hostname = SSH_CANONICALISE_NO; |
1723 | #define CLEAR_ON_NONE(v) \ | 1744 | #define CLEAR_ON_NONE(v) \ |
1724 | do { \ | 1745 | do { \ |
1725 | if (v != NULL && strcasecmp(v, "none") == 0) { \ | 1746 | if (option_clear_or_none(v)) { \ |
1726 | free(v); \ | 1747 | free(v); \ |
1727 | v = NULL; \ | 1748 | v = NULL; \ |
1728 | } \ | 1749 | } \ |
diff --git a/readconf.h b/readconf.h index 9723da078..75e3f8f7a 100644 --- a/readconf.h +++ b/readconf.h | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: readconf.h,v 1.100 2014/01/29 06:18:35 djm Exp $ */ | 1 | /* $OpenBSD: readconf.h,v 1.101 2014/02/23 20:11:36 djm Exp $ */ |
2 | 2 | ||
3 | /* | 3 | /* |
4 | * Author: Tatu Ylonen <ylo@cs.hut.fi> | 4 | * Author: Tatu Ylonen <ylo@cs.hut.fi> |
@@ -176,12 +176,14 @@ typedef struct { | |||
176 | 176 | ||
177 | void initialize_options(Options *); | 177 | void initialize_options(Options *); |
178 | void fill_default_options(Options *); | 178 | void fill_default_options(Options *); |
179 | void fill_default_options_for_canonicalization(Options *); | ||
179 | int process_config_line(Options *, struct passwd *, const char *, char *, | 180 | int process_config_line(Options *, struct passwd *, const char *, char *, |
180 | const char *, int, int *, int); | 181 | const char *, int, int *, int); |
181 | int read_config_file(const char *, struct passwd *, const char *, | 182 | int read_config_file(const char *, struct passwd *, const char *, |
182 | Options *, int); | 183 | Options *, int); |
183 | int parse_forward(Forward *, const char *, int, int); | 184 | int parse_forward(Forward *, const char *, int, int); |
184 | int default_ssh_port(void); | 185 | int default_ssh_port(void); |
186 | int option_clear_or_none(const char *); | ||
185 | 187 | ||
186 | void add_local_forward(Options *, const Forward *); | 188 | void add_local_forward(Options *, const Forward *); |
187 | void add_remote_forward(Options *, const Forward *); | 189 | void add_remote_forward(Options *, const Forward *); |
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: ssh.c,v 1.399 2014/02/04 00:24:29 djm Exp $ */ | 1 | /* $OpenBSD: ssh.c,v 1.400 2014/02/23 20:11:36 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 |
@@ -231,16 +231,26 @@ tilde_expand_paths(char **paths, u_int num_paths) | |||
231 | } | 231 | } |
232 | } | 232 | } |
233 | 233 | ||
234 | /* | ||
235 | * Attempt to resolve a host name / port to a set of addresses and | ||
236 | * optionally return any CNAMEs encountered along the way. | ||
237 | * Returns NULL on failure. | ||
238 | * NB. this function must operate with a options having undefined members. | ||
239 | */ | ||
234 | static struct addrinfo * | 240 | static struct addrinfo * |
235 | resolve_host(const char *name, u_int port, int logerr, char *cname, size_t clen) | 241 | resolve_host(const char *name, int port, int logerr, char *cname, size_t clen) |
236 | { | 242 | { |
237 | char strport[NI_MAXSERV]; | 243 | char strport[NI_MAXSERV]; |
238 | struct addrinfo hints, *res; | 244 | struct addrinfo hints, *res; |
239 | int gaierr, loglevel = SYSLOG_LEVEL_DEBUG1; | 245 | int gaierr, loglevel = SYSLOG_LEVEL_DEBUG1; |
240 | 246 | ||
247 | if (port <= 0) | ||
248 | port = default_ssh_port(); | ||
249 | |||
241 | snprintf(strport, sizeof strport, "%u", port); | 250 | snprintf(strport, sizeof strport, "%u", port); |
242 | memset(&hints, 0, sizeof(hints)); | 251 | memset(&hints, 0, sizeof(hints)); |
243 | hints.ai_family = options.address_family; | 252 | hints.ai_family = options.address_family == -1 ? |
253 | AF_UNSPEC : options.address_family; | ||
244 | hints.ai_socktype = SOCK_STREAM; | 254 | hints.ai_socktype = SOCK_STREAM; |
245 | if (cname != NULL) | 255 | if (cname != NULL) |
246 | hints.ai_flags = AI_CANONNAME; | 256 | hints.ai_flags = AI_CANONNAME; |
@@ -265,6 +275,7 @@ resolve_host(const char *name, u_int port, int logerr, char *cname, size_t clen) | |||
265 | /* | 275 | /* |
266 | * Check whether the cname is a permitted replacement for the hostname | 276 | * Check whether the cname is a permitted replacement for the hostname |
267 | * and perform the replacement if it is. | 277 | * and perform the replacement if it is. |
278 | * NB. this function must operate with a options having undefined members. | ||
268 | */ | 279 | */ |
269 | static int | 280 | static int |
270 | check_follow_cname(char **namep, const char *cname) | 281 | check_follow_cname(char **namep, const char *cname) |
@@ -281,7 +292,7 @@ check_follow_cname(char **namep, const char *cname) | |||
281 | * Don't attempt to canonicalize names that will be interpreted by | 292 | * Don't attempt to canonicalize names that will be interpreted by |
282 | * a proxy unless the user specifically requests so. | 293 | * a proxy unless the user specifically requests so. |
283 | */ | 294 | */ |
284 | if (options.proxy_command != NULL && | 295 | if (!option_clear_or_none(options.proxy_command) && |
285 | options.canonicalize_hostname != SSH_CANONICALISE_ALWAYS) | 296 | options.canonicalize_hostname != SSH_CANONICALISE_ALWAYS) |
286 | return 0; | 297 | return 0; |
287 | debug3("%s: check \"%s\" CNAME \"%s\"", __func__, *namep, cname); | 298 | debug3("%s: check \"%s\" CNAME \"%s\"", __func__, *namep, cname); |
@@ -305,9 +316,10 @@ check_follow_cname(char **namep, const char *cname) | |||
305 | * Attempt to resolve the supplied hostname after applying the user's | 316 | * Attempt to resolve the supplied hostname after applying the user's |
306 | * canonicalization rules. Returns the address list for the host or NULL | 317 | * canonicalization rules. Returns the address list for the host or NULL |
307 | * if no name was found after canonicalization. | 318 | * if no name was found after canonicalization. |
319 | * NB. this function must operate with a options having undefined members. | ||
308 | */ | 320 | */ |
309 | static struct addrinfo * | 321 | static struct addrinfo * |
310 | resolve_canonicalize(char **hostp, u_int port) | 322 | resolve_canonicalize(char **hostp, int port) |
311 | { | 323 | { |
312 | int i, ndots; | 324 | int i, ndots; |
313 | char *cp, *fullhost, cname_target[NI_MAXHOST]; | 325 | char *cp, *fullhost, cname_target[NI_MAXHOST]; |
@@ -315,13 +327,15 @@ resolve_canonicalize(char **hostp, u_int port) | |||
315 | 327 | ||
316 | if (options.canonicalize_hostname == SSH_CANONICALISE_NO) | 328 | if (options.canonicalize_hostname == SSH_CANONICALISE_NO) |
317 | return NULL; | 329 | return NULL; |
330 | |||
318 | /* | 331 | /* |
319 | * Don't attempt to canonicalize names that will be interpreted by | 332 | * Don't attempt to canonicalize names that will be interpreted by |
320 | * a proxy unless the user specifically requests so. | 333 | * a proxy unless the user specifically requests so. |
321 | */ | 334 | */ |
322 | if (options.proxy_command != NULL && | 335 | if (!option_clear_or_none(options.proxy_command) && |
323 | options.canonicalize_hostname != SSH_CANONICALISE_ALWAYS) | 336 | options.canonicalize_hostname != SSH_CANONICALISE_ALWAYS) |
324 | return NULL; | 337 | return NULL; |
338 | |||
325 | /* Don't apply canonicalization to sufficiently-qualified hostnames */ | 339 | /* Don't apply canonicalization to sufficiently-qualified hostnames */ |
326 | ndots = 0; | 340 | ndots = 0; |
327 | for (cp = *hostp; *cp != '\0'; cp++) { | 341 | for (cp = *hostp; *cp != '\0'; cp++) { |
@@ -338,7 +352,9 @@ resolve_canonicalize(char **hostp, u_int port) | |||
338 | *cname_target = '\0'; | 352 | *cname_target = '\0'; |
339 | xasprintf(&fullhost, "%s.%s.", *hostp, | 353 | xasprintf(&fullhost, "%s.%s.", *hostp, |
340 | options.canonical_domains[i]); | 354 | options.canonical_domains[i]); |
341 | if ((addrs = resolve_host(fullhost, options.port, 0, | 355 | debug3("%s: attempting \"%s\" => \"%s\"", __func__, |
356 | *hostp, fullhost); | ||
357 | if ((addrs = resolve_host(fullhost, port, 0, | ||
342 | cname_target, sizeof(cname_target))) == NULL) { | 358 | cname_target, sizeof(cname_target))) == NULL) { |
343 | free(fullhost); | 359 | free(fullhost); |
344 | continue; | 360 | continue; |
@@ -355,11 +371,41 @@ resolve_canonicalize(char **hostp, u_int port) | |||
355 | return addrs; | 371 | return addrs; |
356 | } | 372 | } |
357 | if (!options.canonicalize_fallback_local) | 373 | if (!options.canonicalize_fallback_local) |
358 | fatal("%s: Could not resolve host \"%s\"", __progname, host); | 374 | fatal("%s: Could not resolve host \"%s\"", __progname, *hostp); |
375 | debug2("%s: host %s not found in any suffix", __func__, *hostp); | ||
359 | return NULL; | 376 | return NULL; |
360 | } | 377 | } |
361 | 378 | ||
362 | /* | 379 | /* |
380 | * Read per-user configuration file. Ignore the system wide config | ||
381 | * file if the user specifies a config file on the command line. | ||
382 | */ | ||
383 | static void | ||
384 | process_config_files(struct passwd *pw) | ||
385 | { | ||
386 | char buf[MAXPATHLEN]; | ||
387 | int r; | ||
388 | |||
389 | if (config != NULL) { | ||
390 | if (strcasecmp(config, "none") != 0 && | ||
391 | !read_config_file(config, pw, host, &options, | ||
392 | SSHCONF_USERCONF)) | ||
393 | fatal("Can't open user config file %.100s: " | ||
394 | "%.100s", config, strerror(errno)); | ||
395 | } else { | ||
396 | r = snprintf(buf, sizeof buf, "%s/%s", pw->pw_dir, | ||
397 | _PATH_SSH_USER_CONFFILE); | ||
398 | if (r > 0 && (size_t)r < sizeof(buf)) | ||
399 | (void)read_config_file(buf, pw, host, &options, | ||
400 | SSHCONF_CHECKPERM|SSHCONF_USERCONF); | ||
401 | |||
402 | /* Read systemwide configuration file after user config. */ | ||
403 | (void)read_config_file(_PATH_HOST_CONFIG_FILE, pw, host, | ||
404 | &options, 0); | ||
405 | } | ||
406 | } | ||
407 | |||
408 | /* | ||
363 | * Main program for the ssh client. | 409 | * Main program for the ssh client. |
364 | */ | 410 | */ |
365 | int | 411 | int |
@@ -832,31 +878,54 @@ main(int ac, char **av) | |||
832 | if (debug_flag) | 878 | if (debug_flag) |
833 | logit("%s, %s", SSH_VERSION, SSLeay_version(SSLEAY_VERSION)); | 879 | logit("%s, %s", SSH_VERSION, SSLeay_version(SSLEAY_VERSION)); |
834 | 880 | ||
881 | /* Parse the configuration files */ | ||
882 | process_config_files(pw); | ||
883 | |||
884 | /* Hostname canonicalisation needs a few options filled. */ | ||
885 | fill_default_options_for_canonicalization(&options); | ||
886 | |||
887 | /* If the user has replaced the hostname then take it into use now */ | ||
888 | if (options.hostname != NULL) { | ||
889 | /* NB. Please keep in sync with readconf.c:match_cfg_line() */ | ||
890 | cp = percent_expand(options.hostname, | ||
891 | "h", host, (char *)NULL); | ||
892 | free(host); | ||
893 | host = cp; | ||
894 | } | ||
895 | |||
896 | /* If canonicalization requested then try to apply it */ | ||
897 | lowercase(host); | ||
898 | if (options.canonicalize_hostname != SSH_CANONICALISE_NO) | ||
899 | addrs = resolve_canonicalize(&host, options.port); | ||
900 | |||
835 | /* | 901 | /* |
836 | * Read per-user configuration file. Ignore the system wide config | 902 | * If canonicalization not requested, or if it failed then try to |
837 | * file if the user specifies a config file on the command line. | 903 | * resolve the bare hostname name using the system resolver's usual |
904 | * search rules. Skip the lookup if a ProxyCommand is being used | ||
905 | * unless the user has specifically requested canonicalisation. | ||
838 | */ | 906 | */ |
839 | if (config != NULL) { | 907 | if (addrs == NULL && (option_clear_or_none(options.proxy_command) || |
840 | if (strcasecmp(config, "none") != 0 && | 908 | options.canonicalize_hostname == SSH_CANONICALISE_ALWAYS)) { |
841 | !read_config_file(config, pw, host, &options, | 909 | if ((addrs = resolve_host(host, options.port, 1, |
842 | SSHCONF_USERCONF)) | 910 | cname, sizeof(cname))) == NULL) |
843 | fatal("Can't open user config file %.100s: " | 911 | cleanup_exit(255); /* resolve_host logs the error */ |
844 | "%.100s", config, strerror(errno)); | 912 | check_follow_cname(&host, cname); |
845 | } else { | 913 | } |
846 | r = snprintf(buf, sizeof buf, "%s/%s", pw->pw_dir, | ||
847 | _PATH_SSH_USER_CONFFILE); | ||
848 | if (r > 0 && (size_t)r < sizeof(buf)) | ||
849 | (void)read_config_file(buf, pw, host, &options, | ||
850 | SSHCONF_CHECKPERM|SSHCONF_USERCONF); | ||
851 | 914 | ||
852 | /* Read systemwide configuration file after user config. */ | 915 | /* |
853 | (void)read_config_file(_PATH_HOST_CONFIG_FILE, pw, host, | 916 | * If the target hostname has changed as a result of canonicalisation |
854 | &options, 0); | 917 | * then re-parse the configuration files as new stanzas may match. |
918 | */ | ||
919 | if (strcasecmp(host_arg, host) != 0) { | ||
920 | debug("Hostname has changed; re-reading configuration"); | ||
921 | process_config_files(pw); | ||
855 | } | 922 | } |
856 | 923 | ||
857 | /* Fill configuration defaults. */ | 924 | /* Fill configuration defaults. */ |
858 | fill_default_options(&options); | 925 | fill_default_options(&options); |
859 | 926 | ||
927 | if (options.port == 0) | ||
928 | options.port = default_ssh_port(); | ||
860 | channel_set_af(options.address_family); | 929 | channel_set_af(options.address_family); |
861 | 930 | ||
862 | /* Tidy and check options */ | 931 | /* Tidy and check options */ |
@@ -899,37 +968,6 @@ main(int ac, char **av) | |||
899 | if (options.user == NULL) | 968 | if (options.user == NULL) |
900 | options.user = xstrdup(pw->pw_name); | 969 | options.user = xstrdup(pw->pw_name); |
901 | 970 | ||
902 | /* Get default port if port has not been set. */ | ||
903 | if (options.port == 0) | ||
904 | options.port = default_ssh_port(); | ||
905 | |||
906 | /* preserve host name given on command line for %n expansion */ | ||
907 | if (options.hostname != NULL) { | ||
908 | /* NB. Please keep in sync with readconf.c:match_cfg_line() */ | ||
909 | cp = percent_expand(options.hostname, | ||
910 | "h", host, (char *)NULL); | ||
911 | free(host); | ||
912 | host = cp; | ||
913 | } | ||
914 | |||
915 | /* If canonicalization requested then try to apply it */ | ||
916 | lowercase(host); | ||
917 | if (options.canonicalize_hostname != SSH_CANONICALISE_NO) | ||
918 | addrs = resolve_canonicalize(&host, options.port); | ||
919 | /* | ||
920 | * If canonicalization not requested, or if it failed then try to | ||
921 | * resolve the bare hostname name using the system resolver's usual | ||
922 | * search rules. Skip the lookup if a ProxyCommand is being used | ||
923 | * unless the user has specifically requested canonicalisation. | ||
924 | */ | ||
925 | if (addrs == NULL && (options.proxy_command == NULL || | ||
926 | options.canonicalize_hostname == SSH_CANONICALISE_ALWAYS)) { | ||
927 | if ((addrs = resolve_host(host, options.port, 1, | ||
928 | cname, sizeof(cname))) == NULL) | ||
929 | cleanup_exit(255); /* resolve_host logs the error */ | ||
930 | check_follow_cname(&host, cname); | ||
931 | } | ||
932 | |||
933 | if (gethostname(thishost, sizeof(thishost)) == -1) | 971 | if (gethostname(thishost, sizeof(thishost)) == -1) |
934 | fatal("gethostname: %s", strerror(errno)); | 972 | fatal("gethostname: %s", strerror(errno)); |
935 | strlcpy(shorthost, thishost, sizeof(shorthost)); | 973 | strlcpy(shorthost, thishost, sizeof(shorthost)); |
diff --git a/ssh_config.5 b/ssh_config.5 index 3cadcd767..b5803920f 100644 --- a/ssh_config.5 +++ b/ssh_config.5 | |||
@@ -33,8 +33,8 @@ | |||
33 | .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | 33 | .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
34 | .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 34 | .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
35 | .\" | 35 | .\" |
36 | .\" $OpenBSD: ssh_config.5,v 1.184 2014/01/19 04:48:08 djm Exp $ | 36 | .\" $OpenBSD: ssh_config.5,v 1.185 2014/02/23 20:11:36 djm Exp $ |
37 | .Dd $Mdocdate: January 19 2014 $ | 37 | .Dd $Mdocdate: February 23 2014 $ |
38 | .Dt SSH_CONFIG 5 | 38 | .Dt SSH_CONFIG 5 |
39 | .Os | 39 | .Os |
40 | .Sh NAME | 40 | .Sh NAME |
@@ -263,6 +263,12 @@ If | |||
263 | is set to | 263 | is set to |
264 | .Dq always , | 264 | .Dq always , |
265 | then canonicalization is applied to proxied connections too. | 265 | then canonicalization is applied to proxied connections too. |
266 | .Pp | ||
267 | If this option is enabled and canonicalisation results in the target hostname | ||
268 | changing, then the configuration files are processed again using the new | ||
269 | target name to pick up any new configuration in matching | ||
270 | .Cm Host | ||
271 | stanzas. | ||
266 | .It Cm CanonicalizeMaxDots | 272 | .It Cm CanonicalizeMaxDots |
267 | Specifies the maximum number of dot characters in a hostname before | 273 | Specifies the maximum number of dot characters in a hostname before |
268 | canonicalization is disabled. | 274 | canonicalization is disabled. |