summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDarren Tucker <dtucker@zip.com.au>2008-06-10 23:01:51 +1000
committerDarren Tucker <dtucker@zip.com.au>2008-06-10 23:01:51 +1000
commite7140f20cb2da1456e6080059eef54cf0f3533f2 (patch)
tree7c4809d2dbb4b9e93599a2fb29c51a4621f88346
parentb06cc4abf8e2eb4d1e14f19911a7e0afde50ee95 (diff)
- dtucker@cvs.openbsd.org 2008/06/10 04:50:25
[sshd.c channels.h channels.c log.c servconf.c log.h servconf.h sshd.8] Add extended test mode (-T) and connection parameters for test mode (-C). -T causes sshd to write its effective configuration to stdout and exit. -C causes any relevant Match rules to be applied before output. The combination allows tesing of the parser and config files. ok deraadt djm
-rw-r--r--ChangeLog8
-rw-r--r--channels.c13
-rw-r--r--channels.h3
-rw-r--r--log.c24
-rw-r--r--log.h6
-rw-r--r--servconf.c241
-rw-r--r--servconf.h3
-rw-r--r--sshd.834
-rw-r--r--sshd.c47
9 files changed, 355 insertions, 24 deletions
diff --git a/ChangeLog b/ChangeLog
index e16603175..3c2cc2168 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -12,6 +12,12 @@
12 - djm@cvs.openbsd.org 2008/06/10 04:17:46 12 - djm@cvs.openbsd.org 2008/06/10 04:17:46
13 [sshd_config.5] 13 [sshd_config.5]
14 better reference for pattern-list 14 better reference for pattern-list
15 - dtucker@cvs.openbsd.org 2008/06/10 04:50:25
16 [sshd.c channels.h channels.c log.c servconf.c log.h servconf.h sshd.8]
17 Add extended test mode (-T) and connection parameters for test mode (-C).
18 -T causes sshd to write its effective configuration to stdout and exit.
19 -C causes any relevant Match rules to be applied before output. The
20 combination allows tesing of the parser and config files. ok deraadt djm
15 21
1620080609 2220080609
17 - (dtucker) OpenBSD CVS Sync 23 - (dtucker) OpenBSD CVS Sync
@@ -4098,4 +4104,4 @@
4098 OpenServer 6 and add osr5bigcrypt support so when someone migrates 4104 OpenServer 6 and add osr5bigcrypt support so when someone migrates
4099 passwords between UnixWare and OpenServer they will still work. OK dtucker@ 4105 passwords between UnixWare and OpenServer they will still work. OK dtucker@
4100 4106
4101$Id: ChangeLog,v 1.4950 2008/06/10 12:59:53 dtucker Exp $ 4107$Id: ChangeLog,v 1.4951 2008/06/10 13:01:51 dtucker Exp $
diff --git a/channels.c b/channels.c
index 99b23d75f..6808d3a05 100644
--- a/channels.c
+++ b/channels.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: channels.c,v 1.277 2008/05/09 16:17:51 markus Exp $ */ 1/* $OpenBSD: channels.c,v 1.278 2008/06/10 04:50:25 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
@@ -2784,6 +2784,17 @@ channel_clear_adm_permitted_opens(void)
2784 num_adm_permitted_opens = 0; 2784 num_adm_permitted_opens = 0;
2785} 2785}
2786 2786
2787void
2788channel_print_adm_permitted_opens(void)
2789{
2790 static int i;
2791
2792 for (i = 0; i < num_adm_permitted_opens; i++)
2793 if (permitted_adm_opens[i].host_to_connect != NULL)
2794 printf(" %s:%d", permitted_adm_opens[i].host_to_connect,
2795 permitted_adm_opens[i].port_to_connect);
2796}
2797
2787/* Try to start non-blocking connect to next host in cctx list */ 2798/* Try to start non-blocking connect to next host in cctx list */
2788static int 2799static int
2789connect_next(struct channel_connect *cctx) 2800connect_next(struct channel_connect *cctx)
diff --git a/channels.h b/channels.h
index ec2435df0..dc1f483ed 100644
--- a/channels.h
+++ b/channels.h
@@ -1,4 +1,4 @@
1/* $OpenBSD: channels.h,v 1.92 2008/05/09 16:21:13 markus Exp $ */ 1/* $OpenBSD: channels.h,v 1.93 2008/06/10 04:50:25 dtucker Exp $ */
2 2
3/* 3/*
4 * Author: Tatu Ylonen <ylo@cs.hut.fi> 4 * Author: Tatu Ylonen <ylo@cs.hut.fi>
@@ -235,6 +235,7 @@ void channel_add_permitted_opens(char *, int);
235int channel_add_adm_permitted_opens(char *, int); 235int channel_add_adm_permitted_opens(char *, int);
236void channel_clear_permitted_opens(void); 236void channel_clear_permitted_opens(void);
237void channel_clear_adm_permitted_opens(void); 237void channel_clear_adm_permitted_opens(void);
238void channel_print_adm_permitted_opens(void);
238int channel_input_port_forward_request(int, int); 239int channel_input_port_forward_request(int, int);
239Channel *channel_connect_to(const char *, u_short, char *, char *); 240Channel *channel_connect_to(const char *, u_short, char *, char *);
240Channel *channel_connect_by_listen_address(u_short, char *, char *); 241Channel *channel_connect_by_listen_address(u_short, char *, char *);
diff --git a/log.c b/log.c
index fae5b043f..4a8239b93 100644
--- a/log.c
+++ b/log.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: log.c,v 1.40 2007/05/17 07:50:31 djm Exp $ */ 1/* $OpenBSD: log.c,v 1.41 2008/06/10 04:50:25 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
@@ -114,6 +114,17 @@ log_facility_number(char *name)
114 return SYSLOG_FACILITY_NOT_SET; 114 return SYSLOG_FACILITY_NOT_SET;
115} 115}
116 116
117const char *
118log_facility_name(SyslogFacility facility)
119{
120 u_int i;
121
122 for (i = 0; log_facilities[i].name; i++)
123 if (log_facilities[i].val == facility)
124 return log_facilities[i].name;
125 return NULL;
126}
127
117LogLevel 128LogLevel
118log_level_number(char *name) 129log_level_number(char *name)
119{ 130{
@@ -126,6 +137,17 @@ log_level_number(char *name)
126 return SYSLOG_LEVEL_NOT_SET; 137 return SYSLOG_LEVEL_NOT_SET;
127} 138}
128 139
140const char *
141log_level_name(LogLevel level)
142{
143 u_int i;
144
145 for (i = 0; log_levels[i].name != NULL; i++)
146 if (log_levels[i].val == level)
147 return log_levels[i].name;
148 return NULL;
149}
150
129/* Error messages that should be logged. */ 151/* Error messages that should be logged. */
130 152
131void 153void
diff --git a/log.h b/log.h
index 7a8c57079..fa0996ad5 100644
--- a/log.h
+++ b/log.h
@@ -1,4 +1,4 @@
1/* $OpenBSD: log.h,v 1.15 2006/08/18 09:13:25 deraadt Exp $ */ 1/* $OpenBSD: log.h,v 1.16 2008/06/10 04:50:25 dtucker Exp $ */
2 2
3/* 3/*
4 * Author: Tatu Ylonen <ylo@cs.hut.fi> 4 * Author: Tatu Ylonen <ylo@cs.hut.fi>
@@ -49,7 +49,9 @@ typedef enum {
49void log_init(char *, LogLevel, SyslogFacility, int); 49void log_init(char *, LogLevel, SyslogFacility, int);
50 50
51SyslogFacility log_facility_number(char *); 51SyslogFacility log_facility_number(char *);
52LogLevel log_level_number(char *); 52const char * log_facility_name(SyslogFacility);
53LogLevel log_level_number(char *);
54const char * log_level_name(LogLevel);
53 55
54void fatal(const char *, ...) __dead __attribute__((format(printf, 1, 2))); 56void fatal(const char *, ...) __dead __attribute__((format(printf, 1, 2)));
55void error(const char *, ...) __attribute__((format(printf, 1, 2))); 57void error(const char *, ...) __attribute__((format(printf, 1, 2)));
diff --git a/servconf.c b/servconf.c
index 07a201034..63704fb33 100644
--- a/servconf.c
+++ b/servconf.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: servconf.c,v 1.181 2008/06/10 03:57:27 djm Exp $ */ 1/* $OpenBSD: servconf.c,v 1.182 2008/06/10 04:50:25 dtucker Exp $ */
2/* 2/*
3 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 3 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
4 * All rights reserved 4 * All rights reserved
@@ -23,6 +23,7 @@
23#include <signal.h> 23#include <signal.h>
24#include <unistd.h> 24#include <unistd.h>
25#include <stdarg.h> 25#include <stdarg.h>
26#include <errno.h>
26 27
27#include "openbsd-compat/sys-queue.h" 28#include "openbsd-compat/sys-queue.h"
28#include "xmalloc.h" 29#include "xmalloc.h"
@@ -417,6 +418,17 @@ static struct {
417 { NULL, sBadOption, 0 } 418 { NULL, sBadOption, 0 }
418}; 419};
419 420
421static struct {
422 int val;
423 char *text;
424} tunmode_desc[] = {
425 { SSH_TUNMODE_NO, "no" },
426 { SSH_TUNMODE_POINTOPOINT, "point-to-point" },
427 { SSH_TUNMODE_ETHERNET, "ethernet" },
428 { SSH_TUNMODE_YES, "yes" },
429 { -1, NULL }
430};
431
420/* 432/*
421 * Returns the number of the token pointed to by cp or sBadOption. 433 * Returns the number of the token pointed to by cp or sBadOption.
422 */ 434 */
@@ -1211,16 +1223,13 @@ process_server_config_line(ServerOptions *options, char *line,
1211 if (!arg || *arg == '\0') 1223 if (!arg || *arg == '\0')
1212 fatal("%s line %d: Missing yes/point-to-point/" 1224 fatal("%s line %d: Missing yes/point-to-point/"
1213 "ethernet/no argument.", filename, linenum); 1225 "ethernet/no argument.", filename, linenum);
1214 value = 0; /* silence compiler */ 1226 value = -1;
1215 if (strcasecmp(arg, "ethernet") == 0) 1227 for (i = 0; tunmode_desc[i].val != -1; i++)
1216 value = SSH_TUNMODE_ETHERNET; 1228 if (strcmp(tunmode_desc[i].text, arg) == 0) {
1217 else if (strcasecmp(arg, "point-to-point") == 0) 1229 value = tunmode_desc[i].val;
1218 value = SSH_TUNMODE_POINTOPOINT; 1230 break;
1219 else if (strcasecmp(arg, "yes") == 0) 1231 }
1220 value = SSH_TUNMODE_YES; 1232 if (value == -1)
1221 else if (strcasecmp(arg, "no") == 0)
1222 value = SSH_TUNMODE_NO;
1223 else
1224 fatal("%s line %d: Bad yes/point-to-point/ethernet/" 1233 fatal("%s line %d: Bad yes/point-to-point/ethernet/"
1225 "no argument: %s", filename, linenum, arg); 1234 "no argument: %s", filename, linenum, arg);
1226 if (*intptr == -1) 1235 if (*intptr == -1)
@@ -1426,3 +1435,213 @@ parse_server_config(ServerOptions *options, const char *filename, Buffer *conf,
1426 fatal("%s: terminating, %d bad configuration options", 1435 fatal("%s: terminating, %d bad configuration options",
1427 filename, bad_options); 1436 filename, bad_options);
1428} 1437}
1438
1439static const char *
1440fmt_intarg(ServerOpCodes code, int val)
1441{
1442 if (code == sAddressFamily) {
1443 switch (val) {
1444 case AF_INET:
1445 return "inet";
1446 case AF_INET6:
1447 return "inet6";
1448 case AF_UNSPEC:
1449 return "any";
1450 default:
1451 return "UNKNOWN";
1452 }
1453 }
1454 if (code == sPermitRootLogin) {
1455 switch (val) {
1456 case PERMIT_NO_PASSWD:
1457 return "without-passord";
1458 case PERMIT_FORCED_ONLY:
1459 return "forced-commands-only";
1460 case PERMIT_YES:
1461 return "yes";
1462 }
1463 }
1464 if (code == sProtocol) {
1465 switch (val) {
1466 case SSH_PROTO_1:
1467 return "1";
1468 case SSH_PROTO_2:
1469 return "2";
1470 case (SSH_PROTO_1|SSH_PROTO_2):
1471 return "2,1";
1472 default:
1473 return "UNKNOWN";
1474 }
1475 }
1476 if (code == sGatewayPorts && val == 2)
1477 return "clientspecified";
1478 if (code == sCompression && val == COMP_DELAYED)
1479 return "delayed";
1480 switch (val) {
1481 case -1:
1482 return "unset";
1483 case 0:
1484 return "no";
1485 case 1:
1486 return "yes";
1487 }
1488 return "UNKNOWN";
1489}
1490
1491static const char *
1492lookup_opcode_name(ServerOpCodes code)
1493{
1494 u_int i;
1495
1496 for (i = 0; keywords[i].name != NULL; i++)
1497 if (keywords[i].opcode == code)
1498 return(keywords[i].name);
1499 return "UNKNOWN";
1500}
1501
1502static void
1503dump_cfg_int(ServerOpCodes code, int val)
1504{
1505 printf("%s %d\n", lookup_opcode_name(code), val);
1506}
1507
1508static void
1509dump_cfg_fmtint(ServerOpCodes code, int val)
1510{
1511 printf("%s %s\n", lookup_opcode_name(code), fmt_intarg(code, val));
1512}
1513
1514static void
1515dump_cfg_string(ServerOpCodes code, const char *val)
1516{
1517 if (val == NULL)
1518 return;
1519 printf("%s %s\n", lookup_opcode_name(code), val);
1520}
1521
1522static void
1523dump_cfg_strarray(ServerOpCodes code, u_int count, char **vals)
1524{
1525 u_int i;
1526
1527 for (i = 0; i < count; i++)
1528 printf("%s %s\n", lookup_opcode_name(code), vals[i]);
1529}
1530
1531void
1532dump_config(ServerOptions *o)
1533{
1534 u_int i;
1535 int ret;
1536 struct addrinfo *ai;
1537 char addr[NI_MAXHOST], port[NI_MAXSERV], *s = NULL;
1538
1539 /* these are usually at the top of the config */
1540 for (i = 0; i < o->num_ports; i++)
1541 printf("port %d\n", o->ports[i]);
1542 dump_cfg_fmtint(sProtocol, o->protocol);
1543 dump_cfg_fmtint(sAddressFamily, o->address_family);
1544
1545 /* ListenAddress must be after Port */
1546 for (ai = o->listen_addrs; ai; ai = ai->ai_next) {
1547 if ((ret = getnameinfo(ai->ai_addr, ai->ai_addrlen, addr,
1548 sizeof(addr), port, sizeof(port),
1549 NI_NUMERICHOST|NI_NUMERICSERV)) != 0) {
1550 error("getnameinfo failed: %.100s",
1551 (ret != EAI_SYSTEM) ? gai_strerror(ret) :
1552 strerror(errno));
1553 } else {
1554 if (ai->ai_family == AF_INET6)
1555 printf("listenaddress [%s]:%s\n", addr, port);
1556 else
1557 printf("listenaddress %s:%s\n", addr, port);
1558 }
1559 }
1560
1561 /* integer arguments */
1562 dump_cfg_int(sServerKeyBits, o->server_key_bits);
1563 dump_cfg_int(sLoginGraceTime, o->login_grace_time);
1564 dump_cfg_int(sKeyRegenerationTime, o->key_regeneration_time);
1565 dump_cfg_int(sX11DisplayOffset, o->x11_display_offset);
1566 dump_cfg_int(sMaxAuthTries, o->max_authtries);
1567 dump_cfg_int(sClientAliveInterval, o->client_alive_interval);
1568 dump_cfg_int(sClientAliveCountMax, o->client_alive_count_max);
1569
1570 /* formatted integer arguments */
1571 dump_cfg_fmtint(sPermitRootLogin, o->permit_root_login);
1572 dump_cfg_fmtint(sIgnoreRhosts, o->ignore_rhosts);
1573 dump_cfg_fmtint(sIgnoreUserKnownHosts, o->ignore_user_known_hosts);
1574 dump_cfg_fmtint(sRhostsRSAAuthentication, o->rhosts_rsa_authentication);
1575 dump_cfg_fmtint(sHostbasedAuthentication, o->hostbased_authentication);
1576 dump_cfg_fmtint(sHostbasedUsesNameFromPacketOnly,
1577 o->hostbased_uses_name_from_packet_only);
1578 dump_cfg_fmtint(sRSAAuthentication, o->rsa_authentication);
1579 dump_cfg_fmtint(sPubkeyAuthentication, o->pubkey_authentication);
1580 dump_cfg_fmtint(sKerberosAuthentication, o->kerberos_authentication);
1581 dump_cfg_fmtint(sKerberosOrLocalPasswd, o->kerberos_or_local_passwd);
1582 dump_cfg_fmtint(sKerberosTicketCleanup, o->kerberos_ticket_cleanup);
1583 dump_cfg_fmtint(sKerberosGetAFSToken, o->kerberos_get_afs_token);
1584 dump_cfg_fmtint(sGssAuthentication, o->gss_authentication);
1585 dump_cfg_fmtint(sGssCleanupCreds, o->gss_cleanup_creds);
1586 dump_cfg_fmtint(sPasswordAuthentication, o->password_authentication);
1587 dump_cfg_fmtint(sKbdInteractiveAuthentication,
1588 o->kbd_interactive_authentication);
1589 dump_cfg_fmtint(sChallengeResponseAuthentication,
1590 o->challenge_response_authentication);
1591 dump_cfg_fmtint(sPrintMotd, o->print_motd);
1592 dump_cfg_fmtint(sPrintLastLog, o->print_lastlog);
1593 dump_cfg_fmtint(sX11Forwarding, o->x11_forwarding);
1594 dump_cfg_fmtint(sX11UseLocalhost, o->x11_use_localhost);
1595 dump_cfg_fmtint(sStrictModes, o->strict_modes);
1596 dump_cfg_fmtint(sTCPKeepAlive, o->tcp_keep_alive);
1597 dump_cfg_fmtint(sEmptyPasswd, o->permit_empty_passwd);
1598 dump_cfg_fmtint(sPermitUserEnvironment, o->permit_user_env);
1599 dump_cfg_fmtint(sUseLogin, o->use_login);
1600 dump_cfg_fmtint(sCompression, o->compression);
1601 dump_cfg_fmtint(sGatewayPorts, o->gateway_ports);
1602 dump_cfg_fmtint(sUseDNS, o->use_dns);
1603 dump_cfg_fmtint(sAllowTcpForwarding, o->allow_tcp_forwarding);
1604 dump_cfg_fmtint(sUsePrivilegeSeparation, use_privsep);
1605
1606 /* string arguments */
1607 dump_cfg_string(sPidFile, o->pid_file);
1608 dump_cfg_string(sXAuthLocation, o->xauth_location);
1609 dump_cfg_string(sCiphers, o->ciphers);
1610 dump_cfg_string(sMacs, o->macs);
1611 dump_cfg_string(sBanner, o->banner);
1612 dump_cfg_string(sAuthorizedKeysFile, o->authorized_keys_file);
1613 dump_cfg_string(sAuthorizedKeysFile2, o->authorized_keys_file2);
1614 dump_cfg_string(sForceCommand, o->adm_forced_command);
1615
1616 /* string arguments requiring a lookup */
1617 dump_cfg_string(sLogLevel, log_level_name(o->log_level));
1618 dump_cfg_string(sLogFacility, log_facility_name(o->log_facility));
1619
1620 /* string array arguments */
1621 dump_cfg_strarray(sHostKeyFile, o->num_host_key_files,
1622 o->host_key_files);
1623 dump_cfg_strarray(sAllowUsers, o->num_allow_users, o->allow_users);
1624 dump_cfg_strarray(sDenyUsers, o->num_deny_users, o->deny_users);
1625 dump_cfg_strarray(sAllowGroups, o->num_allow_groups, o->allow_groups);
1626 dump_cfg_strarray(sDenyGroups, o->num_deny_groups, o->deny_groups);
1627 dump_cfg_strarray(sAcceptEnv, o->num_accept_env, o->accept_env);
1628
1629 /* other arguments */
1630 for (i = 0; i < o->num_subsystems; i++)
1631 printf("subsystem %s %s\n", o->subsystem_name[i],
1632 o->subsystem_args[i]);
1633
1634 printf("maxstartups %d:%d:%d\n", o->max_startups_begin,
1635 o->max_startups_rate, o->max_startups);
1636
1637 for (i = 0; tunmode_desc[i].val != -1; i++)
1638 if (tunmode_desc[i].val == o->permit_tun) {
1639 s = tunmode_desc[i].text;
1640 break;
1641 }
1642 dump_cfg_string(sPermitTunnel, s);
1643
1644 printf("permitopen");
1645 channel_print_adm_permitted_opens();
1646 printf("\n");
1647}
diff --git a/servconf.h b/servconf.h
index 819a028c8..40ac64f13 100644
--- a/servconf.h
+++ b/servconf.h
@@ -1,4 +1,4 @@
1/* $OpenBSD: servconf.h,v 1.84 2008/05/08 12:21:16 djm Exp $ */ 1/* $OpenBSD: servconf.h,v 1.85 2008/06/10 04:50:25 dtucker Exp $ */
2 2
3/* 3/*
4 * Author: Tatu Ylonen <ylo@cs.hut.fi> 4 * Author: Tatu Ylonen <ylo@cs.hut.fi>
@@ -161,5 +161,6 @@ void parse_server_config(ServerOptions *, const char *, Buffer *,
161void parse_server_match_config(ServerOptions *, const char *, const char *, 161void parse_server_match_config(ServerOptions *, const char *, const char *,
162 const char *); 162 const char *);
163void copy_set_server_options(ServerOptions *, ServerOptions *, int); 163void copy_set_server_options(ServerOptions *, ServerOptions *, int);
164void dump_config(ServerOptions *);
164 165
165#endif /* SERVCONF_H */ 166#endif /* SERVCONF_H */
diff --git a/sshd.8 b/sshd.8
index 750d64c3e..7274d0928 100644
--- a/sshd.8
+++ b/sshd.8
@@ -34,8 +34,8 @@
34.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 34.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
35.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 35.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36.\" 36.\"
37.\" $OpenBSD: sshd.8,v 1.241 2008/03/27 22:37:57 jmc Exp $ 37.\" $OpenBSD: sshd.8,v 1.242 2008/06/10 04:50:25 dtucker Exp $
38.Dd $Mdocdate: March 27 2008 $ 38.Dd $Mdocdate: June 10 2008 $
39.Dt SSHD 8 39.Dt SSHD 8
40.Os 40.Os
41.Sh NAME 41.Sh NAME
@@ -44,8 +44,9 @@
44.Sh SYNOPSIS 44.Sh SYNOPSIS
45.Nm sshd 45.Nm sshd
46.Bk -words 46.Bk -words
47.Op Fl 46Ddeiqt 47.Op Fl 46DTdeiqt
48.Op Fl b Ar bits 48.Op Fl b Ar bits
49.Op Fl C Ar connection_spec
49.Op Fl f Ar config_file 50.Op Fl f Ar config_file
50.Op Fl g Ar login_grace_time 51.Op Fl g Ar login_grace_time
51.Op Fl h Ar host_key_file 52.Op Fl h Ar host_key_file
@@ -197,6 +198,33 @@ Only check the validity of the configuration file and sanity of the keys.
197This is useful for updating 198This is useful for updating
198.Nm 199.Nm
199reliably as configuration options may change. 200reliably as configuration options may change.
201.It Fl T
202Extended test mode.
203Check the validity of the configuration file, output the effective configuration
204to stdout and then exit.
205Optionally,
206.Cm Match
207rules may be applied by specifying the connection parameters using one or more
208.Fl C
209options.
210.It Fl C
211Specify the connection parameters to use for the the
212.Fl T
213extended test mode.
214If provided, any
215.Cm Match
216directives in the configuration file
217that would apply to the specified user, host and address will be set before
218the configuration is written to standard output.
219The connection parameters are supplied as keyword=value pairs.
220The keywords are
221.Dq user ,
222.Dq host
223and
224.Dq addr
225All are required and may be supplied in any order, either with multiple
226.Fl C
227options or as a comma-separated list.
200.It Fl u Ar len 228.It Fl u Ar len
201This option is used to specify the size of the field 229This option is used to specify the size of the field
202in the 230in the
diff --git a/sshd.c b/sshd.c
index aefbaaa42..ccff65d06 100644
--- a/sshd.c
+++ b/sshd.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: sshd.c,v 1.357 2008/05/08 12:02:23 djm Exp $ */ 1/* $OpenBSD: sshd.c,v 1.358 2008/06/10 04:50:25 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
@@ -1240,8 +1240,9 @@ main(int ac, char **av)
1240 int opt, i, on = 1; 1240 int opt, i, on = 1;
1241 int sock_in = -1, sock_out = -1, newsock = -1; 1241 int sock_in = -1, sock_out = -1, newsock = -1;
1242 const char *remote_ip; 1242 const char *remote_ip;
1243 char *test_user = NULL, *test_host = NULL, *test_addr = NULL;
1243 int remote_port; 1244 int remote_port;
1244 char *line; 1245 char *line, *p, *cp;
1245 int config_s[2] = { -1 , -1 }; 1246 int config_s[2] = { -1 , -1 };
1246 Key *key; 1247 Key *key;
1247 Authctxt *authctxt; 1248 Authctxt *authctxt;
@@ -1276,7 +1277,7 @@ main(int ac, char **av)
1276 initialize_server_options(&options); 1277 initialize_server_options(&options);
1277 1278
1278 /* Parse command-line arguments. */ 1279 /* Parse command-line arguments. */
1279 while ((opt = getopt(ac, av, "f:p:b:k:h:g:u:o:dDeiqrtQR46")) != -1) { 1280 while ((opt = getopt(ac, av, "f:p:b:k:h:g:u:o:C:dDeiqrtQRT46")) != -1) {
1280 switch (opt) { 1281 switch (opt) {
1281 case '4': 1282 case '4':
1282 options.address_family = AF_INET; 1283 options.address_family = AF_INET;
@@ -1354,6 +1355,25 @@ main(int ac, char **av)
1354 case 't': 1355 case 't':
1355 test_flag = 1; 1356 test_flag = 1;
1356 break; 1357 break;
1358 case 'T':
1359 test_flag = 2;
1360 break;
1361 case 'C':
1362 cp = optarg;
1363 while ((p = strsep(&cp, ",")) && *p != '\0') {
1364 if (strncmp(p, "addr=", 5) == 0)
1365 test_addr = xstrdup(p + 5);
1366 else if (strncmp(p, "host=", 5) == 0)
1367 test_host = xstrdup(p + 5);
1368 else if (strncmp(p, "user=", 5) == 0)
1369 test_user = xstrdup(p + 5);
1370 else {
1371 fprintf(stderr, "Invalid test "
1372 "mode specification %s\n", p);
1373 exit(1);
1374 }
1375 }
1376 break;
1357 case 'u': 1377 case 'u':
1358 utmp_len = (u_int)strtonum(optarg, 0, MAXHOSTNAMELEN+1, NULL); 1378 utmp_len = (u_int)strtonum(optarg, 0, MAXHOSTNAMELEN+1, NULL);
1359 if (utmp_len > MAXHOSTNAMELEN) { 1379 if (utmp_len > MAXHOSTNAMELEN) {
@@ -1415,6 +1435,20 @@ main(int ac, char **av)
1415 sensitive_data.have_ssh1_key = 0; 1435 sensitive_data.have_ssh1_key = 0;
1416 sensitive_data.have_ssh2_key = 0; 1436 sensitive_data.have_ssh2_key = 0;
1417 1437
1438 /*
1439 * If we're doing an extended config test, make sure we have all of
1440 * the parameters we need. If we're not doing an extended test,
1441 * do not silently ignore connection test params.
1442 */
1443 if (test_flag >= 2 && (test_user != NULL || test_host != NULL || test_addr != NULL)
1444 && (test_user == NULL || test_host == NULL || test_addr == NULL))
1445 fatal("user, host and addr are all required when testing "
1446 "Match configs");
1447 if (test_flag < 2 && (test_user != NULL || test_host != NULL ||
1448 test_addr != NULL))
1449 fatal("Config test connection parameter (-C) provided without "
1450 "test mode (-T)");
1451
1418 /* Fetch our configuration */ 1452 /* Fetch our configuration */
1419 buffer_init(&cfg); 1453 buffer_init(&cfg);
1420 if (rexeced_flag) 1454 if (rexeced_flag)
@@ -1543,6 +1577,13 @@ main(int ac, char **av)
1543 "world-writable.", _PATH_PRIVSEP_CHROOT_DIR); 1577 "world-writable.", _PATH_PRIVSEP_CHROOT_DIR);
1544 } 1578 }
1545 1579
1580 if (test_flag > 1) {
1581 if (test_user != NULL && test_addr != NULL && test_host != NULL)
1582 parse_server_match_config(&options, test_user,
1583 test_host, test_addr);
1584 dump_config(&options);
1585 }
1586
1546 /* Configuration looks good, so exit if in test mode. */ 1587 /* Configuration looks good, so exit if in test mode. */
1547 if (test_flag) 1588 if (test_flag)
1548 exit(0); 1589 exit(0);