Commit 957fbceb authored by djm@openbsd.org's avatar djm@openbsd.org Committed by Damien Miller

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
parent 5c0dafd3
This diff is collapsed.
/* $OpenBSD: readconf.h,v 1.102 2014/07/15 15:54:14 millert Exp $ */
/* $OpenBSD: readconf.h,v 1.103 2014/10/08 22:20:25 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
......@@ -164,17 +164,19 @@ typedef struct {
#define SSHCONF_CHECKPERM 1 /* check permissions on config file */
#define SSHCONF_USERCONF 2 /* user provided config file not system */
#define SSHCONF_POSTCANON 4 /* After hostname canonicalisation */
void initialize_options(Options *);
void fill_default_options(Options *);
void fill_default_options_for_canonicalization(Options *);
int process_config_line(Options *, struct passwd *, const char *, char *,
const char *, int, int *, int);
int process_config_line(Options *, struct passwd *, const char *,
const char *, char *, const char *, int, int *, int);
int read_config_file(const char *, struct passwd *, const char *,
Options *, int);
const char *, Options *, int);
int parse_forward(struct Forward *, const char *, int, int);
int default_ssh_port(void);
int option_clear_or_none(const char *);
void dump_client_config(Options *o, const char *host);
void add_local_forward(Options *, const struct Forward *);
void add_remote_forward(Options *, const struct Forward *);
......
/* $OpenBSD: ssh-keysign.c,v 1.42 2014/04/29 18:01:49 markus Exp $ */
/* $OpenBSD: ssh-keysign.c,v 1.43 2014/10/08 22:20:25 djm Exp $ */
/*
* Copyright (c) 2002 Markus Friedl. All rights reserved.
*
......@@ -187,7 +187,7 @@ main(int argc, char **argv)
/* verify that ssh-keysign is enabled by the admin */
initialize_options(&options);
(void)read_config_file(_PATH_HOST_CONFIG_FILE, pw, "", &options, 0);
(void)read_config_file(_PATH_HOST_CONFIG_FILE, pw, "", "", &options, 0);
fill_default_options(&options);
if (options.enable_ssh_keysign != 1)
fatal("ssh-keysign not enabled in %s",
......
......@@ -33,8 +33,8 @@
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
.\"
.\" $OpenBSD: ssh.1,v 1.349 2014/08/30 15:33:50 sobrado Exp $
.Dd $Mdocdate: August 30 2014 $
.\" $OpenBSD: ssh.1,v 1.350 2014/10/08 22:20:25 djm Exp $
.Dd $Mdocdate: October 8 2014 $
.Dt SSH 1
.Os
.Sh NAME
......@@ -43,7 +43,7 @@
.Sh SYNOPSIS
.Nm ssh
.Bk -words
.Op Fl 1246AaCfgKkMNnqsTtVvXxYy
.Op Fl 1246AaCfgGKkMNnqsTtVvXxYy
.Op Fl b Ar bind_address
.Op Fl c Ar cipher_spec
.Op Fl D Oo Ar bind_address : Oc Ns Ar port
......@@ -251,6 +251,14 @@ then a client started with
.Fl f
will wait for all remote port forwards to be successfully established
before placing itself in the background.
.It Fl G
Causes
.Nm
to print its configuration after evaluating
.Cm Host
and
.Cm Match
blocks and exit.
.It Fl g
Allows remote hosts to connect to local forwarded ports.
If used on a multiplexed connection, then this option must be specified
......
/* $OpenBSD: ssh.c,v 1.407 2014/07/17 07:22:19 djm Exp $ */
/* $OpenBSD: ssh.c,v 1.408 2014/10/08 22:20:25 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
......@@ -384,27 +384,49 @@ resolve_canonicalize(char **hostp, int port)
* file if the user specifies a config file on the command line.
*/
static void
process_config_files(struct passwd *pw)
process_config_files(const char *host_arg, struct passwd *pw, int post_canon)
{
char buf[MAXPATHLEN];
int r;
if (config != NULL) {
if (strcasecmp(config, "none") != 0 &&
!read_config_file(config, pw, host, &options,
SSHCONF_USERCONF))
!read_config_file(config, pw, host, host_arg, &options,
SSHCONF_USERCONF | (post_canon ? SSHCONF_POSTCANON : 0)))
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);
(void)read_config_file(buf, pw, host, host_arg,
&options, SSHCONF_CHECKPERM | SSHCONF_USERCONF |
(post_canon ? SSHCONF_POSTCANON : 0));
/* Read systemwide configuration file after user config. */
(void)read_config_file(_PATH_HOST_CONFIG_FILE, pw, host,
&options, 0);
(void)read_config_file(_PATH_HOST_CONFIG_FILE, pw,
host, host_arg, &options,
post_canon ? SSHCONF_POSTCANON : 0);
}
}
/* Rewrite the port number in an addrinfo list of addresses */
static void
set_addrinfo_port(struct addrinfo *addrs, int port)
{
struct addrinfo *addr;
for (addr = addrs; addr != NULL; addr = addr->ai_next) {
switch (addr->ai_family) {
case AF_INET:
((struct sockaddr_in *)addr->ai_addr)->
sin_port = htons(port);
break;
case AF_INET6:
((struct sockaddr_in6 *)addr->ai_addr)->
sin6_port = htons(port);
break;
}
}
}
......@@ -414,7 +436,7 @@ process_config_files(struct passwd *pw)
int
main(int ac, char **av)
{
int i, r, opt, exit_status, use_syslog;
int i, r, opt, exit_status, use_syslog, config_test = 0;
char *p, *cp, *line, *argv0, buf[MAXPATHLEN], *host_arg, *logfile;
char thishost[NI_MAXHOST], shorthost[NI_MAXHOST], portstr[NI_MAXSERV];
char cname[NI_MAXHOST];
......@@ -507,7 +529,7 @@ main(int ac, char **av)
again:
while ((opt = getopt(ac, av, "1246ab:c:e:fgi:kl:m:no:p:qstvx"
"ACD:E:F:I:KL:MNO:PQ:R:S:TVw:W:XYy")) != -1) {
"ACD:E:F:GI:KL:MNO:PQ:R:S:TVw:W:XYy")) != -1) {
switch (opt) {
case '1':
options.protocol = SSH_PROTO_1;
......@@ -540,6 +562,9 @@ main(int ac, char **av)
case 'E':
logfile = xstrdup(optarg);
break;
case 'G':
config_test = 1;
break;
case 'Y':
options.forward_x11 = 1;
options.forward_x11_trusted = 1;
......@@ -788,9 +813,9 @@ main(int ac, char **av)
break;
case 'o':
line = xstrdup(optarg);
if (process_config_line(&options, pw, host ? host : "",
line, "command-line", 0, NULL, SSHCONF_USERCONF)
!= 0)
if (process_config_line(&options, pw,
host ? host : "", host ? host : "", line,
"command-line", 0, NULL, SSHCONF_USERCONF) != 0)
exit(255);
free(line);
break;
......@@ -899,7 +924,7 @@ main(int ac, char **av)
);
/* Parse the configuration files */
process_config_files(pw);
process_config_files(host_arg, pw, 0);
/* Hostname canonicalisation needs a few options filled. */
fill_default_options_for_canonicalization(&options);
......@@ -911,6 +936,8 @@ main(int ac, char **av)
"h", host, (char *)NULL);
free(host);
host = cp;
free(options.hostname);
options.hostname = xstrdup(host);
}
/* If canonicalization requested then try to apply it */
......@@ -945,12 +972,22 @@ main(int ac, char **av)
}
/*
* If the target hostname has changed as a result of canonicalisation
* then re-parse the configuration files as new stanzas may match.
* If canonicalisation is enabled 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);
if (options.canonicalize_hostname != 0) {
debug("Re-reading configuration after hostname "
"canonicalisation");
free(options.hostname);
options.hostname = xstrdup(host);
process_config_files(host_arg, pw, 1);
/*
* Address resolution happens early with canonicalisation
* enabled and the port number may have changed since, so
* reset it in address list
*/
if (addrs != NULL && options.port > 0)
set_addrinfo_port(addrs, options.port);
}
/* Fill configuration defaults. */
......@@ -1052,6 +1089,11 @@ main(int ac, char **av)
}
free(conn_hash_hex);
if (config_test) {
dump_client_config(&options, host);
exit(0);
}
if (muxclient_command != 0 && options.control_path == NULL)
fatal("No ControlPath specified for \"-O\" command");
if (options.control_path != NULL)
......
......@@ -33,8 +33,8 @@
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
.\"
.\" $OpenBSD: ssh_config.5,v 1.192 2014/08/30 15:33:50 sobrado Exp $
.Dd $Mdocdate: August 30 2014 $
.\" $OpenBSD: ssh_config.5,v 1.193 2014/10/08 22:20:25 djm Exp $
.Dd $Mdocdate: October 8 2014 $
.Dt SSH_CONFIG 5
.Os
.Sh NAME
......@@ -65,7 +65,10 @@ The configuration files contain sections separated by
.Dq Host
specifications, and that section is only applied for hosts that
match one of the patterns given in the specification.
The matched host name is the one given on the command line.
The matched host name is usually the one given on the command line
(see the
.Cm CanonicalizeHostname
option for exceptions.)
.Pp
Since the first obtained value for each parameter is used, more
host-specific declarations should be given near the beginning of the
......@@ -109,10 +112,12 @@ A single
.Ql *
as a pattern can be used to provide global
defaults for all hosts.
The host is the
The host is usually the
.Ar hostname
argument given on the command line (i.e. the name is not converted to
a canonicalized host name before matching).
argument given on the command line
(see the
.Cm CanonicalizeHostname
option for exceptions.)
.Pp
A pattern entry may be negated by prefixing it with an exclamation mark
.Pq Sq !\& .
......@@ -134,19 +139,40 @@ or
keyword) to be used only when the conditions following the
.Cm Match
keyword are satisfied.
Match conditions are specified using one or more keyword/criteria pairs
Match conditions are specified using one or more critera
or the single token
.Cm all
which matches all criteria.
The available keywords are:
which always matches.
The available criteria keywords are:
.Cm canonical ,
.Cm exec ,
.Cm host ,
.Cm originalhost ,
.Cm user ,
and
.Cm localuser .
The
.Cm all
criteria must appear alone or immediately after
.Cm canonical.
Other criteria may be combined arbitrarily.
All criteria but
.Cm all
and
.Cm canonical
require an argument.
Criteria may be negated by prepending an exclamation mark
.Pq Sq !\& .
.Pp
The
.Cm canonical
keywork matches only when the configuration file is being re-parsed
after hostname canonicalization (see the
.Cm CanonicalizeHostname
option.)
This may be useful to specify conditions that work with canonical host
names only.
The
.Cm exec
keyword executes the specified command under the user's shell.
If the command returns a zero exit status then the condition is considered true.
......@@ -179,7 +205,9 @@ The criteria for the
keyword are matched against the target hostname, after any substitution
by the
.Cm Hostname
option.
or
.Cm CanonicalizeHostname
options.
The
.Cm originalhost
keyword matches against the hostname as it was specified on the command-line.
......@@ -264,10 +292,11 @@ is set to
.Dq always ,
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
If this option is enabled, then the configuration files are processed
again using the new target name to pick up any new configuration in matching
.Cm Host
and
.Cm Match
stanzas.
.It Cm CanonicalizeMaxDots
Specifies the maximum number of dot characters in a hostname before
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment