upstream commit

When doing a config test with sshd -T, only require the
attributes that are actually used in Match criteria rather than (an
incomplete list of) all criteria.  ok djm@, man page help jmc@

OpenBSD-Commit-ID: b4e773c4212d3dea486d0259ae977551aab2c1fc
This commit is contained in:
dtucker@openbsd.org@openbsd.org 2017-11-03 03:18:53 +00:00 committed by Damien Miller
parent c357eed5a5
commit 0208a48517
3 changed files with 46 additions and 42 deletions

View File

@ -1,5 +1,5 @@
/* $OpenBSD: servconf.c,v 1.318 2017/10/25 02:10:39 djm Exp $ */ /* $OpenBSD: servconf.c,v 1.319 2017/11/03 03:18:53 dtucker Exp $ */
/* /*
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved * All rights reserved
@ -927,6 +927,13 @@ out:
return result; return result;
} }
static void
match_test_missing_fatal(const char *criteria, const char *attrib)
{
fatal("'Match %s' in configuration but '%s' not in connection "
"test specification.", criteria, attrib);
}
/* /*
* All of the attributes on a single Match line are ANDed together, so we need * All of the attributes on a single Match line are ANDed together, so we need
* to check every attribute and set the result to zero if any attribute does * to check every attribute and set the result to zero if any attribute does
@ -964,20 +971,24 @@ match_cfg_line(char **condition, int line, struct connection_info *ci)
return -1; return -1;
} }
if (strcasecmp(attrib, "user") == 0) { if (strcasecmp(attrib, "user") == 0) {
if (ci == NULL || ci->user == NULL) { if (ci == NULL) {
result = 0; result = 0;
continue; continue;
} }
if (ci->user == NULL)
match_test_missing_fatal("User", "user");
if (match_pattern_list(ci->user, arg, 0) != 1) if (match_pattern_list(ci->user, arg, 0) != 1)
result = 0; result = 0;
else else
debug("user %.100s matched 'User %.100s' at " debug("user %.100s matched 'User %.100s' at "
"line %d", ci->user, arg, line); "line %d", ci->user, arg, line);
} else if (strcasecmp(attrib, "group") == 0) { } else if (strcasecmp(attrib, "group") == 0) {
if (ci == NULL || ci->user == NULL) { if (ci == NULL) {
result = 0; result = 0;
continue; continue;
} }
if (ci->user == NULL)
match_test_missing_fatal("Group", "user");
switch (match_cfg_line_group(arg, line, ci->user)) { switch (match_cfg_line_group(arg, line, ci->user)) {
case -1: case -1:
return -1; return -1;
@ -985,20 +996,24 @@ match_cfg_line(char **condition, int line, struct connection_info *ci)
result = 0; result = 0;
} }
} else if (strcasecmp(attrib, "host") == 0) { } else if (strcasecmp(attrib, "host") == 0) {
if (ci == NULL || ci->host == NULL) { if (ci == NULL) {
result = 0; result = 0;
continue; continue;
} }
if (ci->host == NULL)
match_test_missing_fatal("Host", "host");
if (match_hostname(ci->host, arg) != 1) if (match_hostname(ci->host, arg) != 1)
result = 0; result = 0;
else else
debug("connection from %.100s matched 'Host " debug("connection from %.100s matched 'Host "
"%.100s' at line %d", ci->host, arg, line); "%.100s' at line %d", ci->host, arg, line);
} else if (strcasecmp(attrib, "address") == 0) { } else if (strcasecmp(attrib, "address") == 0) {
if (ci == NULL || ci->address == NULL) { if (ci == NULL) {
result = 0; result = 0;
continue; continue;
} }
if (ci->address == NULL)
match_test_missing_fatal("Address", "addr");
switch (addr_match_list(ci->address, arg)) { switch (addr_match_list(ci->address, arg)) {
case 1: case 1:
debug("connection from %.100s matched 'Address " debug("connection from %.100s matched 'Address "
@ -1012,10 +1027,13 @@ match_cfg_line(char **condition, int line, struct connection_info *ci)
return -1; return -1;
} }
} else if (strcasecmp(attrib, "localaddress") == 0){ } else if (strcasecmp(attrib, "localaddress") == 0){
if (ci == NULL || ci->laddress == NULL) { if (ci == NULL) {
result = 0; result = 0;
continue; continue;
} }
if (ci->laddress == NULL)
match_test_missing_fatal("LocalAddress",
"laddr");
switch (addr_match_list(ci->laddress, arg)) { switch (addr_match_list(ci->laddress, arg)) {
case 1: case 1:
debug("connection from %.100s matched " debug("connection from %.100s matched "
@ -1035,10 +1053,12 @@ match_cfg_line(char **condition, int line, struct connection_info *ci)
arg); arg);
return -1; return -1;
} }
if (ci == NULL || ci->lport == 0) { if (ci == NULL) {
result = 0; result = 0;
continue; continue;
} }
if (ci->lport == 0)
match_test_missing_fatal("LocalPort", "lport");
/* TODO support port lists */ /* TODO support port lists */
if (port == ci->lport) if (port == ci->lport)
debug("connection from %.100s matched " debug("connection from %.100s matched "
@ -2116,19 +2136,6 @@ int parse_server_match_testspec(struct connection_info *ci, char *spec)
return 0; return 0;
} }
/*
* returns 1 for a complete spec, 0 for partial spec and -1 for an
* empty spec.
*/
int server_match_spec_complete(struct connection_info *ci)
{
if (ci->user && ci->host && ci->address)
return 1; /* complete */
if (!ci->user && !ci->host && !ci->address)
return -1; /* empty */
return 0; /* partial */
}
/* /*
* Copy any supported values that are set. * Copy any supported values that are set.
* *

23
sshd.8
View File

@ -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: sshd.8,v 1.292 2017/10/25 00:19:47 djm Exp $ .\" $OpenBSD: sshd.8,v 1.293 2017/11/03 03:18:53 dtucker Exp $
.Dd $Mdocdate: October 25 2017 $ .Dd $Mdocdate: November 3 2017 $
.Dt SSHD 8 .Dt SSHD 8
.Os .Os
.Sh NAME .Sh NAME
@ -100,21 +100,22 @@ Specify the connection parameters to use for the
extended test mode. extended test mode.
If provided, any If provided, any
.Cm Match .Cm Match
directives in the configuration file directives in the configuration file that would apply are applied before the
that would apply to the specified user, host, and address will be set before configuration is written to standard output.
the configuration is written to standard output. The connection parameters are supplied as keyword=value pairs and may be
The connection parameters are supplied as keyword=value pairs. supplied in any order, either with multiple
.Fl C
options or as a comma-separated list.
The keywords are The keywords are
.Dq addr,
.Dq user , .Dq user ,
.Dq host , .Dq host ,
.Dq laddr , .Dq laddr ,
.Dq lport , .Dq lport ,
.Dq rdomain
and and
.Dq addr . .Dq rdomain
All are required and may be supplied in any order, either with multiple and correspond to source address, user, resolved source host name,
.Fl C local address, local port number and routing domain respectively.
options or as a comma-separated list.
.It Fl c Ar host_certificate_file .It Fl c Ar host_certificate_file
Specifies a path to a certificate file to identify Specifies a path to a certificate file to identify
.Nm .Nm

18
sshd.c
View File

@ -1,4 +1,4 @@
/* $OpenBSD: sshd.c,v 1.497 2017/10/27 00:18:41 djm Exp $ */ /* $OpenBSD: sshd.c,v 1.498 2017/11/03 03:18:53 dtucker 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
@ -1429,7 +1429,7 @@ main(int ac, char **av)
struct sshkey *pubkey; struct sshkey *pubkey;
int keytype; int keytype;
Authctxt *authctxt; Authctxt *authctxt;
struct connection_info *connection_info = get_connection_info(0, 0); struct connection_info *connection_info = NULL;
ssh_malloc_init(); /* must be called before any mallocs */ ssh_malloc_init(); /* must be called before any mallocs */
@ -1545,6 +1545,7 @@ main(int ac, char **av)
test_flag = 2; test_flag = 2;
break; break;
case 'C': case 'C':
connection_info = get_connection_info(0, 0);
if (parse_server_match_testspec(connection_info, if (parse_server_match_testspec(connection_info,
optarg) == -1) optarg) == -1)
exit(1); exit(1);
@ -1613,14 +1614,10 @@ main(int ac, char **av)
sensitive_data.have_ssh2_key = 0; sensitive_data.have_ssh2_key = 0;
/* /*
* If we're doing an extended config test, make sure we have all of * If we're not doing an extended test do not silently ignore connection
* the parameters we need. If we're not doing an extended test, * test params.
* do not silently ignore connection test params.
*/ */
if (test_flag >= 2 && server_match_spec_complete(connection_info) == 0) if (test_flag < 2 && connection_info != NULL)
fatal("user, host and addr are all required when testing "
"Match configs");
if (test_flag < 2 && server_match_spec_complete(connection_info) >= 0)
fatal("Config test connection parameter (-C) provided without " fatal("Config test connection parameter (-C) provided without "
"test mode (-T)"); "test mode (-T)");
@ -1827,8 +1824,7 @@ main(int ac, char **av)
} }
if (test_flag > 1) { if (test_flag > 1) {
if (server_match_spec_complete(connection_info) == 1) parse_server_match_config(&options, connection_info);
parse_server_match_config(&options, connection_info);
dump_config(&options); dump_config(&options);
} }