summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDarren Tucker <dtucker@zip.com.au>2012-05-19 19:37:01 +1000
committerDarren Tucker <dtucker@zip.com.au>2012-05-19 19:37:01 +1000
commitfbcf827559b38f7992e1bd0bcdc4b4ccdf63bc74 (patch)
treef13d5eac3813d70d50c50196716981b79c606063
parent593538911a4d27f11f8d56e32abe141223c25916 (diff)
- (dtucker) OpenBSD CVS Sync
- dtucker@cvs.openbsd.org 2012/05/13 01:42:32 [servconf.h servconf.c sshd.8 sshd.c auth.c sshd_config.5] Add "Match LocalAddress" and "Match LocalPort" to sshd and adjust tests to match. Feedback and ok djm@ markus@.
-rw-r--r--ChangeLog5
-rw-r--r--auth.c7
-rw-r--r--servconf.c163
-rw-r--r--servconf.h22
-rw-r--r--sshd.86
-rw-r--r--sshd.c39
-rw-r--r--sshd_config.56
7 files changed, 181 insertions, 67 deletions
diff --git a/ChangeLog b/ChangeLog
index 9cdce589f..1ed4b228c 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -4,6 +4,11 @@
4 - (dtucker) [configure.ac contrib/Makefile] bz#1996: use AC_PATH_TOOL to find 4 - (dtucker) [configure.ac contrib/Makefile] bz#1996: use AC_PATH_TOOL to find
5 pkg-config so it does the right thing when cross-compiling. Patch from 5 pkg-config so it does the right thing when cross-compiling. Patch from
6 cjwatson at debian org. 6 cjwatson at debian org.
7- (dtucker) OpenBSD CVS Sync
8 - dtucker@cvs.openbsd.org 2012/05/13 01:42:32
9 [servconf.h servconf.c sshd.8 sshd.c auth.c sshd_config.5]
10 Add "Match LocalAddress" and "Match LocalPort" to sshd and adjust tests
11 to match. Feedback and ok djm@ markus@.
7 12
820120504 1320120504
9 - (dtucker) [configure.ac] Include <sys/param.h> rather than <sys/types.h> 14 - (dtucker) [configure.ac] Include <sys/param.h> rather than <sys/types.h>
diff --git a/auth.c b/auth.c
index 976932887..a8cffd5c1 100644
--- a/auth.c
+++ b/auth.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: auth.c,v 1.95 2012/04/11 13:17:54 djm Exp $ */ 1/* $OpenBSD: auth.c,v 1.96 2012/05/13 01:42:32 dtucker Exp $ */
2/* 2/*
3 * Copyright (c) 2000 Markus Friedl. All rights reserved. 3 * Copyright (c) 2000 Markus Friedl. All rights reserved.
4 * 4 *
@@ -545,9 +545,10 @@ getpwnamallow(const char *user)
545#endif 545#endif
546#endif 546#endif
547 struct passwd *pw; 547 struct passwd *pw;
548 struct connection_info *ci = get_connection_info(1, options.use_dns);
548 549
549 parse_server_match_config(&options, user, 550 ci->user = user;
550 get_canonical_hostname(options.use_dns), get_remote_ipaddr()); 551 parse_server_match_config(&options, ci);
551 552
552#if defined(_AIX) && defined(HAVE_SETAUTHDB) 553#if defined(_AIX) && defined(HAVE_SETAUTHDB)
553 aix_setauthdb(user); 554 aix_setauthdb(user);
diff --git a/servconf.c b/servconf.c
index a8a40f97e..12f43c91e 100644
--- a/servconf.c
+++ b/servconf.c
@@ -1,4 +1,5 @@
1/* $OpenBSD: servconf.c,v 1.225 2012/04/12 02:42:32 djm Exp $ */ 1
2/* $OpenBSD: servconf.c,v 1.226 2012/05/13 01:42:32 dtucker Exp $ */
2/* 3/*
3 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
4 * All rights reserved 5 * All rights reserved
@@ -45,6 +46,8 @@
45#include "match.h" 46#include "match.h"
46#include "channels.h" 47#include "channels.h"
47#include "groupaccess.h" 48#include "groupaccess.h"
49#include "canohost.h"
50#include "packet.h"
48 51
49static void add_listen_addr(ServerOptions *, char *, int); 52static void add_listen_addr(ServerOptions *, char *, int);
50static void add_one_listen_addr(ServerOptions *, char *, int); 53static void add_one_listen_addr(ServerOptions *, char *, int);
@@ -539,6 +542,20 @@ add_one_listen_addr(ServerOptions *options, char *addr, int port)
539 options->listen_addrs = aitop; 542 options->listen_addrs = aitop;
540} 543}
541 544
545struct connection_info *
546get_connection_info(int populate, int use_dns)
547{
548 static struct connection_info ci;
549
550 if (!populate)
551 return &ci;
552 ci.host = get_canonical_hostname(use_dns);
553 ci.address = get_remote_ipaddr();
554 ci.laddress = get_local_ipaddr(packet_get_connection_in());
555 ci.lport = get_local_port();
556 return &ci;
557}
558
542/* 559/*
543 * The strategy for the Match blocks is that the config file is parsed twice. 560 * The strategy for the Match blocks is that the config file is parsed twice.
544 * 561 *
@@ -600,20 +617,25 @@ out:
600 return result; 617 return result;
601} 618}
602 619
620/*
621 * All of the attributes on a single Match line are ANDed together, so we need to check every
622 * attribute and set the result to zero if any attribute does not match.
623 */
603static int 624static int
604match_cfg_line(char **condition, int line, const char *user, const char *host, 625match_cfg_line(char **condition, int line, struct connection_info *ci)
605 const char *address)
606{ 626{
607 int result = 1; 627 int result = 1, port;
608 char *arg, *attrib, *cp = *condition; 628 char *arg, *attrib, *cp = *condition;
609 size_t len; 629 size_t len;
610 630
611 if (user == NULL) 631 if (ci == NULL)
612 debug3("checking syntax for 'Match %s'", cp); 632 debug3("checking syntax for 'Match %s'", cp);
613 else 633 else
614 debug3("checking match for '%s' user %s host %s addr %s", cp, 634 debug3("checking match for '%s' user %s host %s addr %s "
615 user ? user : "(null)", host ? host : "(null)", 635 "laddr %s lport %d", cp, ci->user ? ci->user : "(null)",
616 address ? address : "(null)"); 636 ci->host ? ci->host : "(null)",
637 ci->address ? ci->address : "(null)",
638 ci->laddress ? ci->laddress : "(null)", ci->lport);
617 639
618 while ((attrib = strdelim(&cp)) && *attrib != '\0') { 640 while ((attrib = strdelim(&cp)) && *attrib != '\0') {
619 if ((arg = strdelim(&cp)) == NULL || *arg == '\0') { 641 if ((arg = strdelim(&cp)) == NULL || *arg == '\0') {
@@ -622,37 +644,45 @@ match_cfg_line(char **condition, int line, const char *user, const char *host,
622 } 644 }
623 len = strlen(arg); 645 len = strlen(arg);
624 if (strcasecmp(attrib, "user") == 0) { 646 if (strcasecmp(attrib, "user") == 0) {
625 if (!user) { 647 if (ci == NULL || ci->user == NULL) {
626 result = 0; 648 result = 0;
627 continue; 649 continue;
628 } 650 }
629 if (match_pattern_list(user, arg, len, 0) != 1) 651 if (match_pattern_list(ci->user, arg, len, 0) != 1)
630 result = 0; 652 result = 0;
631 else 653 else
632 debug("user %.100s matched 'User %.100s' at " 654 debug("user %.100s matched 'User %.100s' at "
633 "line %d", user, arg, line); 655 "line %d", ci->user, arg, line);
634 } else if (strcasecmp(attrib, "group") == 0) { 656 } else if (strcasecmp(attrib, "group") == 0) {
635 switch (match_cfg_line_group(arg, line, user)) { 657 if (ci == NULL || ci->user == NULL) {
658 result = 0;
659 continue;
660 }
661 switch (match_cfg_line_group(arg, line, ci->user)) {
636 case -1: 662 case -1:
637 return -1; 663 return -1;
638 case 0: 664 case 0:
639 result = 0; 665 result = 0;
640 } 666 }
641 } else if (strcasecmp(attrib, "host") == 0) { 667 } else if (strcasecmp(attrib, "host") == 0) {
642 if (!host) { 668 if (ci == NULL || ci->host == NULL) {
643 result = 0; 669 result = 0;
644 continue; 670 continue;
645 } 671 }
646 if (match_hostname(host, arg, len) != 1) 672 if (match_hostname(ci->host, arg, len) != 1)
647 result = 0; 673 result = 0;
648 else 674 else
649 debug("connection from %.100s matched 'Host " 675 debug("connection from %.100s matched 'Host "
650 "%.100s' at line %d", host, arg, line); 676 "%.100s' at line %d", ci->host, arg, line);
651 } else if (strcasecmp(attrib, "address") == 0) { 677 } else if (strcasecmp(attrib, "address") == 0) {
652 switch (addr_match_list(address, arg)) { 678 if (ci == NULL || ci->address == NULL) {
679 result = 0;
680 continue;
681 }
682 switch (addr_match_list(ci->address, arg)) {
653 case 1: 683 case 1:
654 debug("connection from %.100s matched 'Address " 684 debug("connection from %.100s matched 'Address "
655 "%.100s' at line %d", address, arg, line); 685 "%.100s' at line %d", ci->address, arg, line);
656 break; 686 break;
657 case 0: 687 case 0:
658 case -1: 688 case -1:
@@ -661,12 +691,47 @@ match_cfg_line(char **condition, int line, const char *user, const char *host,
661 case -2: 691 case -2:
662 return -1; 692 return -1;
663 } 693 }
694 } else if (strcasecmp(attrib, "localaddress") == 0){
695 if (ci == NULL || ci->laddress == NULL) {
696 result = 0;
697 continue;
698 }
699 switch (addr_match_list(ci->laddress, arg)) {
700 case 1:
701 debug("connection from %.100s matched "
702 "'LocalAddress %.100s' at line %d",
703 ci->laddress, arg, line);
704 break;
705 case 0:
706 case -1:
707 result = 0;
708 break;
709 case -2:
710 return -1;
711 }
712 } else if (strcasecmp(attrib, "localport") == 0) {
713 if ((port = a2port(arg)) == -1) {
714 error("Invalid LocalPort '%s' on Match line",
715 arg);
716 return -1;
717 }
718 if (ci == NULL || ci->lport == 0) {
719 result = 0;
720 continue;
721 }
722 /* TODO support port lists */
723 if (port == ci->lport)
724 debug("connection from %.100s matched "
725 "'LocalPort %d' at line %d",
726 ci->laddress, port, line);
727 else
728 result = 0;
664 } else { 729 } else {
665 error("Unsupported Match attribute %s", attrib); 730 error("Unsupported Match attribute %s", attrib);
666 return -1; 731 return -1;
667 } 732 }
668 } 733 }
669 if (user != NULL) 734 if (ci != NULL)
670 debug3("match %sfound", result ? "" : "not "); 735 debug3("match %sfound", result ? "" : "not ");
671 *condition = cp; 736 *condition = cp;
672 return result; 737 return result;
@@ -713,8 +778,8 @@ static const struct multistate multistate_privsep[] = {
713 778
714int 779int
715process_server_config_line(ServerOptions *options, char *line, 780process_server_config_line(ServerOptions *options, char *line,
716 const char *filename, int linenum, int *activep, const char *user, 781 const char *filename, int linenum, int *activep,
717 const char *host, const char *address) 782 struct connection_info *connectinfo)
718{ 783{
719 char *cp, **charptr, *arg, *p; 784 char *cp, **charptr, *arg, *p;
720 int cmdline = 0, *intptr, value, value2, n; 785 int cmdline = 0, *intptr, value, value2, n;
@@ -745,7 +810,7 @@ process_server_config_line(ServerOptions *options, char *line,
745 if (*activep && opcode != sMatch) 810 if (*activep && opcode != sMatch)
746 debug3("%s:%d setting %s %s", filename, linenum, arg, cp); 811 debug3("%s:%d setting %s %s", filename, linenum, arg, cp);
747 if (*activep == 0 && !(flags & SSHCFG_MATCH)) { 812 if (*activep == 0 && !(flags & SSHCFG_MATCH)) {
748 if (user == NULL) { 813 if (connectinfo == NULL) {
749 fatal("%s line %d: Directive '%s' is not allowed " 814 fatal("%s line %d: Directive '%s' is not allowed "
750 "within a Match block", filename, linenum, arg); 815 "within a Match block", filename, linenum, arg);
751 } else { /* this is a directive we have already processed */ 816 } else { /* this is a directive we have already processed */
@@ -1316,7 +1381,7 @@ process_server_config_line(ServerOptions *options, char *line,
1316 if (cmdline) 1381 if (cmdline)
1317 fatal("Match directive not supported as a command-line " 1382 fatal("Match directive not supported as a command-line "
1318 "option"); 1383 "option");
1319 value = match_cfg_line(&cp, linenum, user, host, address); 1384 value = match_cfg_line(&cp, linenum, connectinfo);
1320 if (value < 0) 1385 if (value < 0)
1321 fatal("%s line %d: Bad Match condition", filename, 1386 fatal("%s line %d: Bad Match condition", filename,
1322 linenum); 1387 linenum);
@@ -1478,16 +1543,58 @@ load_server_config(const char *filename, Buffer *conf)
1478} 1543}
1479 1544
1480void 1545void
1481parse_server_match_config(ServerOptions *options, const char *user, 1546parse_server_match_config(ServerOptions *options,
1482 const char *host, const char *address) 1547 struct connection_info *connectinfo)
1483{ 1548{
1484 ServerOptions mo; 1549 ServerOptions mo;
1485 1550
1486 initialize_server_options(&mo); 1551 initialize_server_options(&mo);
1487 parse_server_config(&mo, "reprocess config", &cfg, user, host, address); 1552 parse_server_config(&mo, "reprocess config", &cfg, connectinfo);
1488 copy_set_server_options(options, &mo, 0); 1553 copy_set_server_options(options, &mo, 0);
1489} 1554}
1490 1555
1556int parse_server_match_testspec(struct connection_info *ci, char *spec)
1557{
1558 char *p;
1559
1560 while ((p = strsep(&spec, ",")) && *p != '\0') {
1561 if (strncmp(p, "addr=", 5) == 0) {
1562 ci->address = xstrdup(p + 5);
1563 } else if (strncmp(p, "host=", 5) == 0) {
1564 ci->host = xstrdup(p + 5);
1565 } else if (strncmp(p, "user=", 5) == 0) {
1566 ci->user = xstrdup(p + 5);
1567 } else if (strncmp(p, "laddr=", 6) == 0) {
1568 ci->laddress = xstrdup(p + 6);
1569 } else if (strncmp(p, "lport=", 6) == 0) {
1570 ci->lport = a2port(p + 6);
1571 if (ci->lport == -1) {
1572 fprintf(stderr, "Invalid port '%s' in test mode"
1573 " specification %s\n", p+6, p);
1574 return -1;
1575 }
1576 } else {
1577 fprintf(stderr, "Invalid test mode specification %s\n",
1578 p);
1579 return -1;
1580 }
1581 }
1582 return 0;
1583}
1584
1585/*
1586 * returns 1 for a complete spec, 0 for partial spec and -1 for an
1587 * empty spec.
1588 */
1589int server_match_spec_complete(struct connection_info *ci)
1590{
1591 if (ci->user && ci->host && ci->address)
1592 return 1; /* complete */
1593 if (!ci->user && !ci->host && !ci->address)
1594 return -1; /* empty */
1595 return 0; /* partial */
1596}
1597
1491/* Helper macros */ 1598/* Helper macros */
1492#define M_CP_INTOPT(n) do {\ 1599#define M_CP_INTOPT(n) do {\
1493 if (src->n != -1) \ 1600 if (src->n != -1) \
@@ -1561,7 +1668,7 @@ copy_set_server_options(ServerOptions *dst, ServerOptions *src, int preauth)
1561 1668
1562void 1669void
1563parse_server_config(ServerOptions *options, const char *filename, Buffer *conf, 1670parse_server_config(ServerOptions *options, const char *filename, Buffer *conf,
1564 const char *user, const char *host, const char *address) 1671 struct connection_info *connectinfo)
1565{ 1672{
1566 int active, linenum, bad_options = 0; 1673 int active, linenum, bad_options = 0;
1567 char *cp, *obuf, *cbuf; 1674 char *cp, *obuf, *cbuf;
@@ -1569,11 +1676,11 @@ parse_server_config(ServerOptions *options, const char *filename, Buffer *conf,
1569 debug2("%s: config %s len %d", __func__, filename, buffer_len(conf)); 1676 debug2("%s: config %s len %d", __func__, filename, buffer_len(conf));
1570 1677
1571 obuf = cbuf = xstrdup(buffer_ptr(conf)); 1678 obuf = cbuf = xstrdup(buffer_ptr(conf));
1572 active = user ? 0 : 1; 1679 active = connectinfo ? 0 : 1;
1573 linenum = 1; 1680 linenum = 1;
1574 while ((cp = strsep(&cbuf, "\n")) != NULL) { 1681 while ((cp = strsep(&cbuf, "\n")) != NULL) {
1575 if (process_server_config_line(options, cp, filename, 1682 if (process_server_config_line(options, cp, filename,
1576 linenum++, &active, user, host, address) != 0) 1683 linenum++, &active, connectinfo) != 0)
1577 bad_options++; 1684 bad_options++;
1578 } 1685 }
1579 xfree(obuf); 1686 xfree(obuf);
diff --git a/servconf.h b/servconf.h
index 66ba387dd..2ffaecdcd 100644
--- a/servconf.h
+++ b/servconf.h
@@ -1,4 +1,4 @@
1/* $OpenBSD: servconf.h,v 1.100 2012/04/12 02:42:32 djm Exp $ */ 1/* $OpenBSD: servconf.h,v 1.101 2012/05/13 01:42:32 dtucker Exp $ */
2 2
3/* 3/*
4 * Author: Tatu Ylonen <ylo@cs.hut.fi> 4 * Author: Tatu Ylonen <ylo@cs.hut.fi>
@@ -170,6 +170,16 @@ typedef struct {
170 char *version_addendum; /* Appended to SSH banner */ 170 char *version_addendum; /* Appended to SSH banner */
171} ServerOptions; 171} ServerOptions;
172 172
173/* Information about the incoming connection as used by Match */
174struct connection_info {
175 const char *user;
176 const char *host; /* possibly resolved hostname */
177 const char *address; /* remote address */
178 const char *laddress; /* local address */
179 int lport; /* local port */
180};
181
182
173/* 183/*
174 * These are string config options that must be copied between the 184 * These are string config options that must be copied between the
175 * Match sub-config and the main config, and must be sent from the 185 * Match sub-config and the main config, and must be sent from the
@@ -184,15 +194,17 @@ typedef struct {
184 M_CP_STRARRAYOPT(authorized_keys_files, num_authkeys_files); \ 194 M_CP_STRARRAYOPT(authorized_keys_files, num_authkeys_files); \
185 } while (0) 195 } while (0)
186 196
197struct connection_info *get_connection_info(int, int);
187void initialize_server_options(ServerOptions *); 198void initialize_server_options(ServerOptions *);
188void fill_default_server_options(ServerOptions *); 199void fill_default_server_options(ServerOptions *);
189int process_server_config_line(ServerOptions *, char *, const char *, int, 200int process_server_config_line(ServerOptions *, char *, const char *, int,
190 int *, const char *, const char *, const char *); 201 int *, struct connection_info *);
191void load_server_config(const char *, Buffer *); 202void load_server_config(const char *, Buffer *);
192void parse_server_config(ServerOptions *, const char *, Buffer *, 203void parse_server_config(ServerOptions *, const char *, Buffer *,
193 const char *, const char *, const char *); 204 struct connection_info *);
194void parse_server_match_config(ServerOptions *, const char *, const char *, 205void parse_server_match_config(ServerOptions *, struct connection_info *);
195 const char *); 206int parse_server_match_testspec(struct connection_info *, char *);
207int server_match_spec_complete(struct connection_info *);
196void copy_set_server_options(ServerOptions *, ServerOptions *, int); 208void copy_set_server_options(ServerOptions *, ServerOptions *, int);
197void dump_config(ServerOptions *); 209void dump_config(ServerOptions *);
198char *derelativise_path(const char *); 210char *derelativise_path(const char *);
diff --git a/sshd.8 b/sshd.8
index 721015709..6d79c7dda 100644
--- a/sshd.8
+++ b/sshd.8
@@ -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: sshd.8,v 1.264 2011/09/23 00:22:04 dtucker Exp $ 36.\" $OpenBSD: sshd.8,v 1.265 2012/05/13 01:42:32 dtucker Exp $
37.Dd $Mdocdate: September 23 2011 $ 37.Dd $Mdocdate: May 13 2012 $
38.Dt SSHD 8 38.Dt SSHD 8
39.Os 39.Os
40.Sh NAME 40.Sh NAME
@@ -114,6 +114,8 @@ The connection parameters are supplied as keyword=value pairs.
114The keywords are 114The keywords are
115.Dq user , 115.Dq user ,
116.Dq host , 116.Dq host ,
117.Dq laddr ,
118.Dq lport ,
117and 119and
118.Dq addr . 120.Dq addr .
119All are required and may be supplied in any order, either with multiple 121All are required and may be supplied in any order, either with multiple
diff --git a/sshd.c b/sshd.c
index b7066df5c..7cc7044be 100644
--- a/sshd.c
+++ b/sshd.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: sshd.c,v 1.390 2012/04/12 02:42:32 djm Exp $ */ 1/* $OpenBSD: sshd.c,v 1.391 2012/05/13 01:42:32 dtucker 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
@@ -1325,14 +1325,14 @@ main(int ac, char **av)
1325 int opt, i, j, on = 1; 1325 int opt, i, j, on = 1;
1326 int sock_in = -1, sock_out = -1, newsock = -1; 1326 int sock_in = -1, sock_out = -1, newsock = -1;
1327 const char *remote_ip; 1327 const char *remote_ip;
1328 char *test_user = NULL, *test_host = NULL, *test_addr = NULL;
1329 int remote_port; 1328 int remote_port;
1330 char *line, *p, *cp; 1329 char *line;
1331 int config_s[2] = { -1 , -1 }; 1330 int config_s[2] = { -1 , -1 };
1332 u_int64_t ibytes, obytes; 1331 u_int64_t ibytes, obytes;
1333 mode_t new_umask; 1332 mode_t new_umask;
1334 Key *key; 1333 Key *key;
1335 Authctxt *authctxt; 1334 Authctxt *authctxt;
1335 struct connection_info *connection_info = get_connection_info(0, 0);
1336 1336
1337#ifdef HAVE_SECUREWARE 1337#ifdef HAVE_SECUREWARE
1338 (void)set_auth_parameters(ac, av); 1338 (void)set_auth_parameters(ac, av);
@@ -1454,20 +1454,9 @@ main(int ac, char **av)
1454 test_flag = 2; 1454 test_flag = 2;
1455 break; 1455 break;
1456 case 'C': 1456 case 'C':
1457 cp = optarg; 1457 if (parse_server_match_testspec(connection_info,
1458 while ((p = strsep(&cp, ",")) && *p != '\0') { 1458 optarg) == -1)
1459 if (strncmp(p, "addr=", 5) == 0) 1459 exit(1);
1460 test_addr = xstrdup(p + 5);
1461 else if (strncmp(p, "host=", 5) == 0)
1462 test_host = xstrdup(p + 5);
1463 else if (strncmp(p, "user=", 5) == 0)
1464 test_user = xstrdup(p + 5);
1465 else {
1466 fprintf(stderr, "Invalid test "
1467 "mode specification %s\n", p);
1468 exit(1);
1469 }
1470 }
1471 break; 1460 break;
1472 case 'u': 1461 case 'u':
1473 utmp_len = (u_int)strtonum(optarg, 0, MAXHOSTNAMELEN+1, NULL); 1462 utmp_len = (u_int)strtonum(optarg, 0, MAXHOSTNAMELEN+1, NULL);
@@ -1479,7 +1468,7 @@ main(int ac, char **av)
1479 case 'o': 1468 case 'o':
1480 line = xstrdup(optarg); 1469 line = xstrdup(optarg);
1481 if (process_server_config_line(&options, line, 1470 if (process_server_config_line(&options, line,
1482 "command-line", 0, NULL, NULL, NULL, NULL) != 0) 1471 "command-line", 0, NULL, NULL) != 0)
1483 exit(1); 1472 exit(1);
1484 xfree(line); 1473 xfree(line);
1485 break; 1474 break;
@@ -1535,13 +1524,10 @@ main(int ac, char **av)
1535 * the parameters we need. If we're not doing an extended test, 1524 * the parameters we need. If we're not doing an extended test,
1536 * do not silently ignore connection test params. 1525 * do not silently ignore connection test params.
1537 */ 1526 */
1538 if (test_flag >= 2 && 1527 if (test_flag >= 2 && server_match_spec_complete(connection_info) == 0)
1539 (test_user != NULL || test_host != NULL || test_addr != NULL)
1540 && (test_user == NULL || test_host == NULL || test_addr == NULL))
1541 fatal("user, host and addr are all required when testing " 1528 fatal("user, host and addr are all required when testing "
1542 "Match configs"); 1529 "Match configs");
1543 if (test_flag < 2 && (test_user != NULL || test_host != NULL || 1530 if (test_flag < 2 && server_match_spec_complete(connection_info) >= 0)
1544 test_addr != NULL))
1545 fatal("Config test connection parameter (-C) provided without " 1531 fatal("Config test connection parameter (-C) provided without "
1546 "test mode (-T)"); 1532 "test mode (-T)");
1547 1533
@@ -1553,7 +1539,7 @@ main(int ac, char **av)
1553 load_server_config(config_file_name, &cfg); 1539 load_server_config(config_file_name, &cfg);
1554 1540
1555 parse_server_config(&options, rexeced_flag ? "rexec" : config_file_name, 1541 parse_server_config(&options, rexeced_flag ? "rexec" : config_file_name,
1556 &cfg, NULL, NULL, NULL); 1542 &cfg, NULL);
1557 1543
1558 seed_rng(); 1544 seed_rng();
1559 1545
@@ -1715,9 +1701,8 @@ main(int ac, char **av)
1715 } 1701 }
1716 1702
1717 if (test_flag > 1) { 1703 if (test_flag > 1) {
1718 if (test_user != NULL && test_addr != NULL && test_host != NULL) 1704 if (server_match_spec_complete(connection_info) == 1)
1719 parse_server_match_config(&options, test_user, 1705 parse_server_match_config(&options, connection_info);
1720 test_host, test_addr);
1721 dump_config(&options); 1706 dump_config(&options);
1722 } 1707 }
1723 1708
diff --git a/sshd_config.5 b/sshd_config.5
index 27ee19146..17df9e6cd 100644
--- a/sshd_config.5
+++ b/sshd_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: sshd_config.5,v 1.138 2012/04/12 02:43:55 djm Exp $ 36.\" $OpenBSD: sshd_config.5,v 1.139 2012/05/13 01:42:32 dtucker Exp $
37.Dd $Mdocdate: April 12 2012 $ 37.Dd $Mdocdate: May 13 2012 $
38.Dt SSHD_CONFIG 5 38.Dt SSHD_CONFIG 5
39.Os 39.Os
40.Sh NAME 40.Sh NAME
@@ -677,6 +677,8 @@ The available criteria are
677.Cm User , 677.Cm User ,
678.Cm Group , 678.Cm Group ,
679.Cm Host , 679.Cm Host ,
680.Cm LocalAddress ,
681.Cm LocalPort ,
680and 682and
681.Cm Address . 683.Cm Address .
682The match patterns may consist of single entries or comma-separated 684The match patterns may consist of single entries or comma-separated