View | Details | Raw Unified | Return to bug 2906
Collapse All | Expand All

(-)a/readconf.c (-15 / +27 lines)
Lines 118-127 Link Here
118
118
119
static int read_config_file_depth(const char *filename, struct passwd *pw,
119
static int read_config_file_depth(const char *filename, struct passwd *pw,
120
    const char *host, const char *original_host, Options *options,
120
    const char *host, const char *original_host, Options *options,
121
    int flags, int *activep, int depth);
121
    int flags, int *activep, int *want_final_pass, int depth);
122
static int process_config_line_depth(Options *options, struct passwd *pw,
122
static int process_config_line_depth(Options *options, struct passwd *pw,
123
    const char *host, const char *original_host, char *line,
123
    const char *host, const char *original_host, char *line,
124
    const char *filename, int linenum, int *activep, int flags, int depth);
124
    const char *filename, int linenum, int *activep, int flags,
125
    int *want_final_pass, int depth);
125
126
126
/* Keyword tokens. */
127
/* Keyword tokens. */
127
128
Lines 524-531 execute_in_shell(const char *cmd) Link Here
524
 */
525
 */
525
static int
526
static int
526
match_cfg_line(Options *options, char **condition, struct passwd *pw,
527
match_cfg_line(Options *options, char **condition, struct passwd *pw,
527
    const char *host_arg, const char *original_host, int post_canon,
528
    const char *host_arg, const char *original_host, int final_pass,
528
    const char *filename, int linenum)
529
    int *want_final_pass, const char *filename, int linenum)
529
{
530
{
530
	char *arg, *oattrib, *attrib, *cmd, *cp = *condition, *host, *criteria;
531
	char *arg, *oattrib, *attrib, *cmd, *cp = *condition, *host, *criteria;
531
	const char *ruser;
532
	const char *ruser;
Lines 539-545 match_cfg_line(Options *options, char **condition, struct passwd *pw, Link Here
539
	 */
540
	 */
540
	port = options->port <= 0 ? default_ssh_port() : options->port;
541
	port = options->port <= 0 ? default_ssh_port() : options->port;
541
	ruser = options->user == NULL ? pw->pw_name : options->user;
542
	ruser = options->user == NULL ? pw->pw_name : options->user;
542
	if (post_canon) {
543
	if (final_pass) {
543
		host = xstrdup(options->hostname);
544
		host = xstrdup(options->hostname);
544
	} else if (options->hostname != NULL) {
545
	} else if (options->hostname != NULL) {
545
		/* NB. Please keep in sync with ssh.c:main() */
546
		/* NB. Please keep in sync with ssh.c:main() */
Lines 571-578 match_cfg_line(Options *options, char **condition, struct passwd *pw, Link Here
571
			goto out;
572
			goto out;
572
		}
573
		}
573
		attributes++;
574
		attributes++;
574
		if (strcasecmp(attrib, "canonical") == 0) {
575
		if (strcasecmp(attrib, "canonical") == 0 ||
575
			r = !!post_canon;  /* force bitmask member to boolean */
576
		    strcasecmp(attrib, "final") == 0) {
577
			/*
578
			 * If the config requests "Match final" then remember
579
			 * this so we can perform a second pass later.
580
			 */
581
			if (strcasecmp(attrib, "final") == 0 &&
582
			    want_final_pass != NULL)
583
				*want_final_pass = 1;
584
			r = !!final_pass;  /* force bitmask member to boolean */
576
			if (r == (negate ? 1 : 0))
585
			if (r == (negate ? 1 : 0))
577
				this_result = result = 0;
586
				this_result = result = 0;
578
			debug3("%.200s line %d: %smatched '%s'",
587
			debug3("%.200s line %d: %smatched '%s'",
Lines 809-822 process_config_line(Options *options, struct passwd *pw, const char *host, Link Here
809
    int linenum, int *activep, int flags)
818
    int linenum, int *activep, int flags)
810
{
819
{
811
	return process_config_line_depth(options, pw, host, original_host,
820
	return process_config_line_depth(options, pw, host, original_host,
812
	    line, filename, linenum, activep, flags, 0);
821
	    line, filename, linenum, activep, flags, NULL, 0);
813
}
822
}
814
823
815
#define WHITESPACE " \t\r\n"
824
#define WHITESPACE " \t\r\n"
816
static int
825
static int
817
process_config_line_depth(Options *options, struct passwd *pw, const char *host,
826
process_config_line_depth(Options *options, struct passwd *pw, const char *host,
818
    const char *original_host, char *line, const char *filename,
827
    const char *original_host, char *line, const char *filename,
819
    int linenum, int *activep, int flags, int depth)
828
    int linenum, int *activep, int flags, int *want_final_pass, int depth)
820
{
829
{
821
	char *s, **charptr, *endofnumber, *keyword, *arg, *arg2;
830
	char *s, **charptr, *endofnumber, *keyword, *arg, *arg2;
822
	char **cpptr, fwdarg[256];
831
	char **cpptr, fwdarg[256];
Lines 1315-1321 parse_keytypes: Link Here
1315
			fatal("Host directive not supported as a command-line "
1324
			fatal("Host directive not supported as a command-line "
1316
			    "option");
1325
			    "option");
1317
		value = match_cfg_line(options, &s, pw, host, original_host,
1326
		value = match_cfg_line(options, &s, pw, host, original_host,
1318
		    flags & SSHCONF_POSTCANON, filename, linenum);
1327
		    flags & SSHCONF_FINAL, want_final_pass,
1328
		    filename, linenum);
1319
		if (value < 0)
1329
		if (value < 0)
1320
			fatal("%.200s line %d: Bad Match condition", filename,
1330
			fatal("%.200s line %d: Bad Match condition", filename,
1321
			    linenum);
1331
			    linenum);
Lines 1524-1530 parse_keytypes: Link Here
1524
				    pw, host, original_host, options,
1534
				    pw, host, original_host, options,
1525
				    flags | SSHCONF_CHECKPERM |
1535
				    flags | SSHCONF_CHECKPERM |
1526
				    (oactive ? 0 : SSHCONF_NEVERMATCH),
1536
				    (oactive ? 0 : SSHCONF_NEVERMATCH),
1527
				    activep, depth + 1);
1537
				    activep, want_final_pass, depth + 1);
1528
				if (r != 1 && errno != ENOENT) {
1538
				if (r != 1 && errno != ENOENT) {
1529
					fatal("Can't open user config file "
1539
					fatal("Can't open user config file "
1530
					    "%.100s: %.100s", gl.gl_pathv[i],
1540
					    "%.100s: %.100s", gl.gl_pathv[i],
Lines 1716-1734 parse_keytypes: Link Here
1716
 */
1726
 */
1717
int
1727
int
1718
read_config_file(const char *filename, struct passwd *pw, const char *host,
1728
read_config_file(const char *filename, struct passwd *pw, const char *host,
1719
    const char *original_host, Options *options, int flags)
1729
    const char *original_host, Options *options, int flags,
1730
    int *want_final_pass)
1720
{
1731
{
1721
	int active = 1;
1732
	int active = 1;
1722
1733
1723
	return read_config_file_depth(filename, pw, host, original_host,
1734
	return read_config_file_depth(filename, pw, host, original_host,
1724
	    options, flags, &active, 0);
1735
	    options, flags, &active, want_final_pass, 0);
1725
}
1736
}
1726
1737
1727
#define READCONF_MAX_DEPTH	16
1738
#define READCONF_MAX_DEPTH	16
1728
static int
1739
static int
1729
read_config_file_depth(const char *filename, struct passwd *pw,
1740
read_config_file_depth(const char *filename, struct passwd *pw,
1730
    const char *host, const char *original_host, Options *options,
1741
    const char *host, const char *original_host, Options *options,
1731
    int flags, int *activep, int depth)
1742
    int flags, int *activep, int *want_final_pass, int depth)
1732
{
1743
{
1733
	FILE *f;
1744
	FILE *f;
1734
	char *line = NULL;
1745
	char *line = NULL;
Lines 1763-1769 read_config_file_depth(const char *filename, struct passwd *pw, Link Here
1763
		/* Update line number counter. */
1774
		/* Update line number counter. */
1764
		linenum++;
1775
		linenum++;
1765
		if (process_config_line_depth(options, pw, host, original_host,
1776
		if (process_config_line_depth(options, pw, host, original_host,
1766
		    line, filename, linenum, activep, flags, depth) != 0)
1777
		    line, filename, linenum, activep, flags, want_final_pass,
1778
		    depth) != 0)
1767
			bad_options++;
1779
			bad_options++;
1768
	}
1780
	}
1769
	free(line);
1781
	free(line);
(-)a/readconf.h (-2 / +2 lines)
Lines 185-191 typedef struct { Link Here
185
185
186
#define SSHCONF_CHECKPERM	1  /* check permissions on config file */
186
#define SSHCONF_CHECKPERM	1  /* check permissions on config file */
187
#define SSHCONF_USERCONF	2  /* user provided config file not system */
187
#define SSHCONF_USERCONF	2  /* user provided config file not system */
188
#define SSHCONF_POSTCANON	4  /* After hostname canonicalisation */
188
#define SSHCONF_FINAL		4  /* Final pass over config, after canon. */
189
#define SSHCONF_NEVERMATCH	8  /* Match/Host never matches; internal only */
189
#define SSHCONF_NEVERMATCH	8  /* Match/Host never matches; internal only */
190
190
191
#define SSH_UPDATE_HOSTKEYS_NO	0
191
#define SSH_UPDATE_HOSTKEYS_NO	0
Lines 203-209 void fill_default_options_for_canonicalization(Options *); Link Here
203
int	 process_config_line(Options *, struct passwd *, const char *,
203
int	 process_config_line(Options *, struct passwd *, const char *,
204
    const char *, char *, const char *, int, int *, int);
204
    const char *, char *, const char *, int, int *, int);
205
int	 read_config_file(const char *, struct passwd *, const char *,
205
int	 read_config_file(const char *, struct passwd *, const char *,
206
    const char *, Options *, int);
206
    const char *, Options *, int, int *);
207
int	 parse_forward(struct Forward *, const char *, int, int);
207
int	 parse_forward(struct Forward *, const char *, int, int);
208
int	 parse_jump(const char *, Options *, int);
208
int	 parse_jump(const char *, Options *, int);
209
int	 parse_ssh_uri(const char *, char **, char **, int *);
209
int	 parse_ssh_uri(const char *, char **, char **, int *);
(-)a/ssh.c (-10 / +19 lines)
Lines 511-517 check_load(int r, const char *path, const char *message) Link Here
511
 * file if the user specifies a config file on the command line.
511
 * file if the user specifies a config file on the command line.
512
 */
512
 */
513
static void
513
static void
514
process_config_files(const char *host_name, struct passwd *pw, int post_canon)
514
process_config_files(const char *host_name, struct passwd *pw, int final_pass,
515
    int *want_final_pass)
515
{
516
{
516
	char buf[PATH_MAX];
517
	char buf[PATH_MAX];
517
	int r;
518
	int r;
Lines 519-525 process_config_files(const char *host_name, struct passwd *pw, int post_canon) Link Here
519
	if (config != NULL) {
520
	if (config != NULL) {
520
		if (strcasecmp(config, "none") != 0 &&
521
		if (strcasecmp(config, "none") != 0 &&
521
		    !read_config_file(config, pw, host, host_name, &options,
522
		    !read_config_file(config, pw, host, host_name, &options,
522
		    SSHCONF_USERCONF | (post_canon ? SSHCONF_POSTCANON : 0)))
523
		    SSHCONF_USERCONF | (final_pass ? SSHCONF_FINAL : 0),
524
		    want_final_pass))
523
			fatal("Can't open user config file %.100s: "
525
			fatal("Can't open user config file %.100s: "
524
			    "%.100s", config, strerror(errno));
526
			    "%.100s", config, strerror(errno));
525
	} else {
527
	} else {
Lines 528-539 process_config_files(const char *host_name, struct passwd *pw, int post_canon) Link Here
528
		if (r > 0 && (size_t)r < sizeof(buf))
530
		if (r > 0 && (size_t)r < sizeof(buf))
529
			(void)read_config_file(buf, pw, host, host_name,
531
			(void)read_config_file(buf, pw, host, host_name,
530
			    &options, SSHCONF_CHECKPERM | SSHCONF_USERCONF |
532
			    &options, SSHCONF_CHECKPERM | SSHCONF_USERCONF |
531
			    (post_canon ? SSHCONF_POSTCANON : 0));
533
			    (final_pass ? SSHCONF_FINAL : 0), want_final_pass);
532
534
533
		/* Read systemwide configuration file after user config. */
535
		/* Read systemwide configuration file after user config. */
534
		(void)read_config_file(_PATH_HOST_CONFIG_FILE, pw,
536
		(void)read_config_file(_PATH_HOST_CONFIG_FILE, pw,
535
		    host, host_name, &options,
537
		    host, host_name, &options,
536
		    post_canon ? SSHCONF_POSTCANON : 0);
538
		    final_pass ? SSHCONF_FINAL : 0, want_final_pass);
537
	}
539
	}
538
}
540
}
539
541
Lines 565-571 main(int ac, char **av) Link Here
565
{
567
{
566
	struct ssh *ssh = NULL;
568
	struct ssh *ssh = NULL;
567
	int i, r, opt, exit_status, use_syslog, direct, timeout_ms;
569
	int i, r, opt, exit_status, use_syslog, direct, timeout_ms;
568
	int was_addr, config_test = 0, opt_terminated = 0;
570
	int was_addr, config_test = 0, opt_terminated = 0, want_final_pass = 0;
569
	char *p, *cp, *line, *argv0, buf[PATH_MAX], *logfile;
571
	char *p, *cp, *line, *argv0, buf[PATH_MAX], *logfile;
570
	char cname[NI_MAXHOST];
572
	char cname[NI_MAXHOST];
571
	struct stat st;
573
	struct stat st;
Lines 1068-1074 main(int ac, char **av) Link Here
1068
		);
1070
		);
1069
1071
1070
	/* Parse the configuration files */
1072
	/* Parse the configuration files */
1071
	process_config_files(host_arg, pw, 0);
1073
	process_config_files(host_arg, pw, 0, &want_final_pass);
1074
	if (want_final_pass)
1075
		debug("configuration requests final Match pass");
1072
1076
1073
	/* Hostname canonicalisation needs a few options filled. */
1077
	/* Hostname canonicalisation needs a few options filled. */
1074
	fill_default_options_for_canonicalization(&options);
1078
	fill_default_options_for_canonicalization(&options);
Lines 1125-1136 main(int ac, char **av) Link Here
1125
	 * If canonicalisation is enabled then re-parse the configuration
1129
	 * If canonicalisation is enabled then re-parse the configuration
1126
	 * files as new stanzas may match.
1130
	 * files as new stanzas may match.
1127
	 */
1131
	 */
1128
	if (options.canonicalize_hostname != 0) {
1132
	if (options.canonicalize_hostname != 0 && !want_final_pass) {
1129
		debug("Re-reading configuration after hostname "
1133
		debug("hostname canonicalisation enabled, "
1130
		    "canonicalisation");
1134
		    "will re-parse configuration");
1135
		want_final_pass = 1;
1136
	}
1137
1138
	if (want_final_pass) {
1139
		debug("re-parsing configuration");
1131
		free(options.hostname);
1140
		free(options.hostname);
1132
		options.hostname = xstrdup(host);
1141
		options.hostname = xstrdup(host);
1133
		process_config_files(host_arg, pw, 1);
1142
		process_config_files(host_arg, pw, 1, NULL);
1134
		/*
1143
		/*
1135
		 * Address resolution happens early with canonicalisation
1144
		 * Address resolution happens early with canonicalisation
1136
		 * enabled and the port number may have changed since, so
1145
		 * enabled and the port number may have changed since, so
(-)a/ssh_config.5 (-2 / +20 lines)
Lines 139-144 or the single token Link Here
139
which always matches.
139
which always matches.
140
The available criteria keywords are:
140
The available criteria keywords are:
141
.Cm canonical ,
141
.Cm canonical ,
142
.Cm final ,
142
.Cm exec ,
143
.Cm exec ,
143
.Cm host ,
144
.Cm host ,
144
.Cm originalhost ,
145
.Cm originalhost ,
Lines 148-159 and Link Here
148
The
149
The
149
.Cm all
150
.Cm all
150
criteria must appear alone or immediately after
151
criteria must appear alone or immediately after
151
.Cm canonical .
152
.Cm canonical
153
or
154
.Cm final .
152
Other criteria may be combined arbitrarily.
155
Other criteria may be combined arbitrarily.
153
All criteria but
156
All criteria but
154
.Cm all
157
.Cm all
155
and
156
.Cm canonical
158
.Cm canonical
159
and
160
.Cm final
157
require an argument.
161
require an argument.
158
Criteria may be negated by prepending an exclamation mark
162
Criteria may be negated by prepending an exclamation mark
159
.Pq Sq !\& .
163
.Pq Sq !\& .
Lines 166-171 after hostname canonicalization (see the Link Here
166
option.)
170
option.)
167
This may be useful to specify conditions that work with canonical host
171
This may be useful to specify conditions that work with canonical host
168
names only.
172
names only.
173
.Pp
174
The
175
.Cm final
176
keyword requests that the configuration be re-parsed (regardless of whether
177
.Cm CanonicalizeHostname
178
is enabled), and matches only during this final pass.
179
If
180
.Cm CanonicalizeHostname
181
is enabled, then
182
.Cm canonical
183
and
184
.Cm final
185
match during the same pass.
186
.Pp
169
The
187
The
170
.Cm exec
188
.Cm exec
171
keyword executes the specified command under the user's shell.
189
keyword executes the specified command under the user's shell.

Return to bug 2906