- 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@
This commit is contained in:
parent
bee3a234f3
commit
13f97b2286
16
ChangeLog
16
ChangeLog
|
@ -16,6 +16,22 @@
|
||||||
[ssh-ed25519.c]
|
[ssh-ed25519.c]
|
||||||
check for unsigned overflow; not reachable in OpenSSH but others might
|
check for unsigned overflow; not reachable in OpenSSH but others might
|
||||||
copy our code...
|
copy our code...
|
||||||
|
- 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@
|
||||||
|
|
||||||
20140213
|
20140213
|
||||||
- (dtucker) [configure.ac openbsd-compat/openssl-compat.{c,h}] Add compat
|
- (dtucker) [configure.ac openbsd-compat/openssl-compat.{c,h}] Add compat
|
||||||
|
|
27
readconf.c
27
readconf.c
|
@ -1,4 +1,4 @@
|
||||||
/* $OpenBSD: readconf.c,v 1.217 2014/02/22 01:32:19 djm Exp $ */
|
/* $OpenBSD: readconf.c,v 1.218 2014/02/23 20:11:36 djm Exp $ */
|
||||||
/*
|
/*
|
||||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||||
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
* 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,
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Returns 1 if a string option is unset or set to "none" or 0 otherwise. */
|
||||||
|
int
|
||||||
|
option_clear_or_none(const char *o)
|
||||||
|
{
|
||||||
|
return o == NULL || strcasecmp(o, "none") == 0;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Initializes options to special values that indicate that they have not yet
|
* Initializes options to special values that indicate that they have not yet
|
||||||
* been set. Read_config_file will only set options with this value. Options
|
* been set. Read_config_file will only set options with this value. Options
|
||||||
|
@ -1563,11 +1570,25 @@ initialize_options(Options * options)
|
||||||
options->canonicalize_hostname = -1;
|
options->canonicalize_hostname = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* A petite version of fill_default_options() that just fills the options
|
||||||
|
* needed for hostname canonicalization to proceed.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
fill_default_options_for_canonicalization(Options *options)
|
||||||
|
{
|
||||||
|
if (options->canonicalize_max_dots == -1)
|
||||||
|
options->canonicalize_max_dots = 1;
|
||||||
|
if (options->canonicalize_fallback_local == -1)
|
||||||
|
options->canonicalize_fallback_local = 1;
|
||||||
|
if (options->canonicalize_hostname == -1)
|
||||||
|
options->canonicalize_hostname = SSH_CANONICALISE_NO;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Called after processing other sources of option data, this fills those
|
* Called after processing other sources of option data, this fills those
|
||||||
* options for which no value has been specified with their default values.
|
* options for which no value has been specified with their default values.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void
|
void
|
||||||
fill_default_options(Options * options)
|
fill_default_options(Options * options)
|
||||||
{
|
{
|
||||||
|
@ -1722,7 +1743,7 @@ fill_default_options(Options * options)
|
||||||
options->canonicalize_hostname = SSH_CANONICALISE_NO;
|
options->canonicalize_hostname = SSH_CANONICALISE_NO;
|
||||||
#define CLEAR_ON_NONE(v) \
|
#define CLEAR_ON_NONE(v) \
|
||||||
do { \
|
do { \
|
||||||
if (v != NULL && strcasecmp(v, "none") == 0) { \
|
if (option_clear_or_none(v)) { \
|
||||||
free(v); \
|
free(v); \
|
||||||
v = NULL; \
|
v = NULL; \
|
||||||
} \
|
} \
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* $OpenBSD: readconf.h,v 1.100 2014/01/29 06:18:35 djm Exp $ */
|
/* $OpenBSD: readconf.h,v 1.101 2014/02/23 20:11:36 djm Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||||
|
@ -176,12 +176,14 @@ typedef struct {
|
||||||
|
|
||||||
void initialize_options(Options *);
|
void initialize_options(Options *);
|
||||||
void fill_default_options(Options *);
|
void fill_default_options(Options *);
|
||||||
|
void fill_default_options_for_canonicalization(Options *);
|
||||||
int process_config_line(Options *, struct passwd *, const char *, char *,
|
int process_config_line(Options *, struct passwd *, const char *, char *,
|
||||||
const char *, int, int *, int);
|
const char *, int, int *, int);
|
||||||
int read_config_file(const char *, struct passwd *, const char *,
|
int read_config_file(const char *, struct passwd *, const char *,
|
||||||
Options *, int);
|
Options *, int);
|
||||||
int parse_forward(Forward *, const char *, int, int);
|
int parse_forward(Forward *, const char *, int, int);
|
||||||
int default_ssh_port(void);
|
int default_ssh_port(void);
|
||||||
|
int option_clear_or_none(const char *);
|
||||||
|
|
||||||
void add_local_forward(Options *, const Forward *);
|
void add_local_forward(Options *, const Forward *);
|
||||||
void add_remote_forward(Options *, const Forward *);
|
void add_remote_forward(Options *, const Forward *);
|
||||||
|
|
154
ssh.c
154
ssh.c
|
@ -1,4 +1,4 @@
|
||||||
/* $OpenBSD: ssh.c,v 1.399 2014/02/04 00:24:29 djm Exp $ */
|
/* $OpenBSD: ssh.c,v 1.400 2014/02/23 20:11:36 djm Exp $ */
|
||||||
/*
|
/*
|
||||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||||
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||||
|
@ -231,16 +231,26 @@ tilde_expand_paths(char **paths, u_int num_paths)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Attempt to resolve a host name / port to a set of addresses and
|
||||||
|
* optionally return any CNAMEs encountered along the way.
|
||||||
|
* Returns NULL on failure.
|
||||||
|
* NB. this function must operate with a options having undefined members.
|
||||||
|
*/
|
||||||
static struct addrinfo *
|
static struct addrinfo *
|
||||||
resolve_host(const char *name, u_int port, int logerr, char *cname, size_t clen)
|
resolve_host(const char *name, int port, int logerr, char *cname, size_t clen)
|
||||||
{
|
{
|
||||||
char strport[NI_MAXSERV];
|
char strport[NI_MAXSERV];
|
||||||
struct addrinfo hints, *res;
|
struct addrinfo hints, *res;
|
||||||
int gaierr, loglevel = SYSLOG_LEVEL_DEBUG1;
|
int gaierr, loglevel = SYSLOG_LEVEL_DEBUG1;
|
||||||
|
|
||||||
|
if (port <= 0)
|
||||||
|
port = default_ssh_port();
|
||||||
|
|
||||||
snprintf(strport, sizeof strport, "%u", port);
|
snprintf(strport, sizeof strport, "%u", port);
|
||||||
memset(&hints, 0, sizeof(hints));
|
memset(&hints, 0, sizeof(hints));
|
||||||
hints.ai_family = options.address_family;
|
hints.ai_family = options.address_family == -1 ?
|
||||||
|
AF_UNSPEC : options.address_family;
|
||||||
hints.ai_socktype = SOCK_STREAM;
|
hints.ai_socktype = SOCK_STREAM;
|
||||||
if (cname != NULL)
|
if (cname != NULL)
|
||||||
hints.ai_flags = AI_CANONNAME;
|
hints.ai_flags = AI_CANONNAME;
|
||||||
|
@ -265,6 +275,7 @@ resolve_host(const char *name, u_int port, int logerr, char *cname, size_t clen)
|
||||||
/*
|
/*
|
||||||
* Check whether the cname is a permitted replacement for the hostname
|
* Check whether the cname is a permitted replacement for the hostname
|
||||||
* and perform the replacement if it is.
|
* and perform the replacement if it is.
|
||||||
|
* NB. this function must operate with a options having undefined members.
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
check_follow_cname(char **namep, const char *cname)
|
check_follow_cname(char **namep, const char *cname)
|
||||||
|
@ -281,7 +292,7 @@ check_follow_cname(char **namep, const char *cname)
|
||||||
* Don't attempt to canonicalize names that will be interpreted by
|
* Don't attempt to canonicalize names that will be interpreted by
|
||||||
* a proxy unless the user specifically requests so.
|
* a proxy unless the user specifically requests so.
|
||||||
*/
|
*/
|
||||||
if (options.proxy_command != NULL &&
|
if (!option_clear_or_none(options.proxy_command) &&
|
||||||
options.canonicalize_hostname != SSH_CANONICALISE_ALWAYS)
|
options.canonicalize_hostname != SSH_CANONICALISE_ALWAYS)
|
||||||
return 0;
|
return 0;
|
||||||
debug3("%s: check \"%s\" CNAME \"%s\"", __func__, *namep, cname);
|
debug3("%s: check \"%s\" CNAME \"%s\"", __func__, *namep, cname);
|
||||||
|
@ -305,9 +316,10 @@ check_follow_cname(char **namep, const char *cname)
|
||||||
* Attempt to resolve the supplied hostname after applying the user's
|
* Attempt to resolve the supplied hostname after applying the user's
|
||||||
* canonicalization rules. Returns the address list for the host or NULL
|
* canonicalization rules. Returns the address list for the host or NULL
|
||||||
* if no name was found after canonicalization.
|
* if no name was found after canonicalization.
|
||||||
|
* NB. this function must operate with a options having undefined members.
|
||||||
*/
|
*/
|
||||||
static struct addrinfo *
|
static struct addrinfo *
|
||||||
resolve_canonicalize(char **hostp, u_int port)
|
resolve_canonicalize(char **hostp, int port)
|
||||||
{
|
{
|
||||||
int i, ndots;
|
int i, ndots;
|
||||||
char *cp, *fullhost, cname_target[NI_MAXHOST];
|
char *cp, *fullhost, cname_target[NI_MAXHOST];
|
||||||
|
@ -315,13 +327,15 @@ resolve_canonicalize(char **hostp, u_int port)
|
||||||
|
|
||||||
if (options.canonicalize_hostname == SSH_CANONICALISE_NO)
|
if (options.canonicalize_hostname == SSH_CANONICALISE_NO)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Don't attempt to canonicalize names that will be interpreted by
|
* Don't attempt to canonicalize names that will be interpreted by
|
||||||
* a proxy unless the user specifically requests so.
|
* a proxy unless the user specifically requests so.
|
||||||
*/
|
*/
|
||||||
if (options.proxy_command != NULL &&
|
if (!option_clear_or_none(options.proxy_command) &&
|
||||||
options.canonicalize_hostname != SSH_CANONICALISE_ALWAYS)
|
options.canonicalize_hostname != SSH_CANONICALISE_ALWAYS)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
/* Don't apply canonicalization to sufficiently-qualified hostnames */
|
/* Don't apply canonicalization to sufficiently-qualified hostnames */
|
||||||
ndots = 0;
|
ndots = 0;
|
||||||
for (cp = *hostp; *cp != '\0'; cp++) {
|
for (cp = *hostp; *cp != '\0'; cp++) {
|
||||||
|
@ -338,7 +352,9 @@ resolve_canonicalize(char **hostp, u_int port)
|
||||||
*cname_target = '\0';
|
*cname_target = '\0';
|
||||||
xasprintf(&fullhost, "%s.%s.", *hostp,
|
xasprintf(&fullhost, "%s.%s.", *hostp,
|
||||||
options.canonical_domains[i]);
|
options.canonical_domains[i]);
|
||||||
if ((addrs = resolve_host(fullhost, options.port, 0,
|
debug3("%s: attempting \"%s\" => \"%s\"", __func__,
|
||||||
|
*hostp, fullhost);
|
||||||
|
if ((addrs = resolve_host(fullhost, port, 0,
|
||||||
cname_target, sizeof(cname_target))) == NULL) {
|
cname_target, sizeof(cname_target))) == NULL) {
|
||||||
free(fullhost);
|
free(fullhost);
|
||||||
continue;
|
continue;
|
||||||
|
@ -355,10 +371,40 @@ resolve_canonicalize(char **hostp, u_int port)
|
||||||
return addrs;
|
return addrs;
|
||||||
}
|
}
|
||||||
if (!options.canonicalize_fallback_local)
|
if (!options.canonicalize_fallback_local)
|
||||||
fatal("%s: Could not resolve host \"%s\"", __progname, host);
|
fatal("%s: Could not resolve host \"%s\"", __progname, *hostp);
|
||||||
|
debug2("%s: host %s not found in any suffix", __func__, *hostp);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Read per-user configuration file. Ignore the system wide config
|
||||||
|
* file if the user specifies a config file on the command line.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
process_config_files(struct passwd *pw)
|
||||||
|
{
|
||||||
|
char buf[MAXPATHLEN];
|
||||||
|
int r;
|
||||||
|
|
||||||
|
if (config != NULL) {
|
||||||
|
if (strcasecmp(config, "none") != 0 &&
|
||||||
|
!read_config_file(config, pw, host, &options,
|
||||||
|
SSHCONF_USERCONF))
|
||||||
|
fatal("Can't open user config file %.100s: "
|
||||||
|
"%.100s", config, strerror(errno));
|
||||||
|
} else {
|
||||||
|
r = snprintf(buf, sizeof buf, "%s/%s", pw->pw_dir,
|
||||||
|
_PATH_SSH_USER_CONFFILE);
|
||||||
|
if (r > 0 && (size_t)r < sizeof(buf))
|
||||||
|
(void)read_config_file(buf, pw, host, &options,
|
||||||
|
SSHCONF_CHECKPERM|SSHCONF_USERCONF);
|
||||||
|
|
||||||
|
/* Read systemwide configuration file after user config. */
|
||||||
|
(void)read_config_file(_PATH_HOST_CONFIG_FILE, pw, host,
|
||||||
|
&options, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Main program for the ssh client.
|
* Main program for the ssh client.
|
||||||
*/
|
*/
|
||||||
|
@ -832,31 +878,54 @@ main(int ac, char **av)
|
||||||
if (debug_flag)
|
if (debug_flag)
|
||||||
logit("%s, %s", SSH_VERSION, SSLeay_version(SSLEAY_VERSION));
|
logit("%s, %s", SSH_VERSION, SSLeay_version(SSLEAY_VERSION));
|
||||||
|
|
||||||
/*
|
/* Parse the configuration files */
|
||||||
* Read per-user configuration file. Ignore the system wide config
|
process_config_files(pw);
|
||||||
* file if the user specifies a config file on the command line.
|
|
||||||
*/
|
|
||||||
if (config != NULL) {
|
|
||||||
if (strcasecmp(config, "none") != 0 &&
|
|
||||||
!read_config_file(config, pw, host, &options,
|
|
||||||
SSHCONF_USERCONF))
|
|
||||||
fatal("Can't open user config file %.100s: "
|
|
||||||
"%.100s", config, strerror(errno));
|
|
||||||
} else {
|
|
||||||
r = snprintf(buf, sizeof buf, "%s/%s", pw->pw_dir,
|
|
||||||
_PATH_SSH_USER_CONFFILE);
|
|
||||||
if (r > 0 && (size_t)r < sizeof(buf))
|
|
||||||
(void)read_config_file(buf, pw, host, &options,
|
|
||||||
SSHCONF_CHECKPERM|SSHCONF_USERCONF);
|
|
||||||
|
|
||||||
/* Read systemwide configuration file after user config. */
|
/* Hostname canonicalisation needs a few options filled. */
|
||||||
(void)read_config_file(_PATH_HOST_CONFIG_FILE, pw, host,
|
fill_default_options_for_canonicalization(&options);
|
||||||
&options, 0);
|
|
||||||
|
/* If the user has replaced the hostname then take it into use now */
|
||||||
|
if (options.hostname != NULL) {
|
||||||
|
/* NB. Please keep in sync with readconf.c:match_cfg_line() */
|
||||||
|
cp = percent_expand(options.hostname,
|
||||||
|
"h", host, (char *)NULL);
|
||||||
|
free(host);
|
||||||
|
host = cp;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If canonicalization requested then try to apply it */
|
||||||
|
lowercase(host);
|
||||||
|
if (options.canonicalize_hostname != SSH_CANONICALISE_NO)
|
||||||
|
addrs = resolve_canonicalize(&host, options.port);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If canonicalization not requested, or if it failed then try to
|
||||||
|
* resolve the bare hostname name using the system resolver's usual
|
||||||
|
* search rules. Skip the lookup if a ProxyCommand is being used
|
||||||
|
* unless the user has specifically requested canonicalisation.
|
||||||
|
*/
|
||||||
|
if (addrs == NULL && (option_clear_or_none(options.proxy_command) ||
|
||||||
|
options.canonicalize_hostname == SSH_CANONICALISE_ALWAYS)) {
|
||||||
|
if ((addrs = resolve_host(host, options.port, 1,
|
||||||
|
cname, sizeof(cname))) == NULL)
|
||||||
|
cleanup_exit(255); /* resolve_host logs the error */
|
||||||
|
check_follow_cname(&host, cname);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If the target hostname has changed as a result of canonicalisation
|
||||||
|
* then re-parse the configuration files as new stanzas may match.
|
||||||
|
*/
|
||||||
|
if (strcasecmp(host_arg, host) != 0) {
|
||||||
|
debug("Hostname has changed; re-reading configuration");
|
||||||
|
process_config_files(pw);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Fill configuration defaults. */
|
/* Fill configuration defaults. */
|
||||||
fill_default_options(&options);
|
fill_default_options(&options);
|
||||||
|
|
||||||
|
if (options.port == 0)
|
||||||
|
options.port = default_ssh_port();
|
||||||
channel_set_af(options.address_family);
|
channel_set_af(options.address_family);
|
||||||
|
|
||||||
/* Tidy and check options */
|
/* Tidy and check options */
|
||||||
|
@ -899,37 +968,6 @@ main(int ac, char **av)
|
||||||
if (options.user == NULL)
|
if (options.user == NULL)
|
||||||
options.user = xstrdup(pw->pw_name);
|
options.user = xstrdup(pw->pw_name);
|
||||||
|
|
||||||
/* Get default port if port has not been set. */
|
|
||||||
if (options.port == 0)
|
|
||||||
options.port = default_ssh_port();
|
|
||||||
|
|
||||||
/* preserve host name given on command line for %n expansion */
|
|
||||||
if (options.hostname != NULL) {
|
|
||||||
/* NB. Please keep in sync with readconf.c:match_cfg_line() */
|
|
||||||
cp = percent_expand(options.hostname,
|
|
||||||
"h", host, (char *)NULL);
|
|
||||||
free(host);
|
|
||||||
host = cp;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If canonicalization requested then try to apply it */
|
|
||||||
lowercase(host);
|
|
||||||
if (options.canonicalize_hostname != SSH_CANONICALISE_NO)
|
|
||||||
addrs = resolve_canonicalize(&host, options.port);
|
|
||||||
/*
|
|
||||||
* If canonicalization not requested, or if it failed then try to
|
|
||||||
* resolve the bare hostname name using the system resolver's usual
|
|
||||||
* search rules. Skip the lookup if a ProxyCommand is being used
|
|
||||||
* unless the user has specifically requested canonicalisation.
|
|
||||||
*/
|
|
||||||
if (addrs == NULL && (options.proxy_command == NULL ||
|
|
||||||
options.canonicalize_hostname == SSH_CANONICALISE_ALWAYS)) {
|
|
||||||
if ((addrs = resolve_host(host, options.port, 1,
|
|
||||||
cname, sizeof(cname))) == NULL)
|
|
||||||
cleanup_exit(255); /* resolve_host logs the error */
|
|
||||||
check_follow_cname(&host, cname);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (gethostname(thishost, sizeof(thishost)) == -1)
|
if (gethostname(thishost, sizeof(thishost)) == -1)
|
||||||
fatal("gethostname: %s", strerror(errno));
|
fatal("gethostname: %s", strerror(errno));
|
||||||
strlcpy(shorthost, thishost, sizeof(shorthost));
|
strlcpy(shorthost, thishost, sizeof(shorthost));
|
||||||
|
|
10
ssh_config.5
10
ssh_config.5
|
@ -33,8 +33,8 @@
|
||||||
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||||
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
.\"
|
.\"
|
||||||
.\" $OpenBSD: ssh_config.5,v 1.184 2014/01/19 04:48:08 djm Exp $
|
.\" $OpenBSD: ssh_config.5,v 1.185 2014/02/23 20:11:36 djm Exp $
|
||||||
.Dd $Mdocdate: January 19 2014 $
|
.Dd $Mdocdate: February 23 2014 $
|
||||||
.Dt SSH_CONFIG 5
|
.Dt SSH_CONFIG 5
|
||||||
.Os
|
.Os
|
||||||
.Sh NAME
|
.Sh NAME
|
||||||
|
@ -263,6 +263,12 @@ If
|
||||||
is set to
|
is set to
|
||||||
.Dq always ,
|
.Dq always ,
|
||||||
then canonicalization is applied to proxied connections too.
|
then canonicalization is applied to proxied connections too.
|
||||||
|
.Pp
|
||||||
|
If this option is enabled and canonicalisation results in the target hostname
|
||||||
|
changing, then the configuration files are processed again using the new
|
||||||
|
target name to pick up any new configuration in matching
|
||||||
|
.Cm Host
|
||||||
|
stanzas.
|
||||||
.It Cm CanonicalizeMaxDots
|
.It Cm CanonicalizeMaxDots
|
||||||
Specifies the maximum number of dot characters in a hostname before
|
Specifies the maximum number of dot characters in a hostname before
|
||||||
canonicalization is disabled.
|
canonicalization is disabled.
|
||||||
|
|
Loading…
Reference in New Issue