summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--usr.bin/ssh/auth.c5
-rw-r--r--usr.bin/ssh/servconf.c349
-rw-r--r--usr.bin/ssh/servconf.h11
-rw-r--r--usr.bin/ssh/sshd.c17
-rw-r--r--usr.bin/ssh/sshd_config.523
5 files changed, 298 insertions, 107 deletions
diff --git a/usr.bin/ssh/auth.c b/usr.bin/ssh/auth.c
index ac76a3c5fc4..bc053f95a7f 100644
--- a/usr.bin/ssh/auth.c
+++ b/usr.bin/ssh/auth.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: auth.c,v 1.70 2006/07/11 20:07:25 stevesk Exp $ */
+/* $OpenBSD: auth.c,v 1.71 2006/07/12 11:34:58 dtucker Exp $ */
/*
* Copyright (c) 2000 Markus Friedl. All rights reserved.
*
@@ -385,6 +385,9 @@ getpwnamallow(const char *user)
#endif
struct passwd *pw;
+ parse_server_match_config(&options, user,
+ get_canonical_hostname(options.use_dns), get_remote_ipaddr());
+
pw = getpwnam(user);
if (pw == NULL) {
logit("Invalid user %.100s from %.100s",
diff --git a/usr.bin/ssh/servconf.c b/usr.bin/ssh/servconf.c
index 1b6611c580c..1d97d20c2c6 100644
--- a/usr.bin/ssh/servconf.c
+++ b/usr.bin/ssh/servconf.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: servconf.c,v 1.152 2006/07/08 21:47:12 stevesk Exp $ */
+/* $OpenBSD: servconf.c,v 1.153 2006/07/12 11:34:58 dtucker Exp $ */
/*
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
@@ -25,12 +25,14 @@
#include "cipher.h"
#include "kex.h"
#include "mac.h"
+#include "match.h"
static void add_listen_addr(ServerOptions *, char *, u_short);
static void add_one_listen_addr(ServerOptions *, char *, u_short);
/* Use of privilege separation or not */
extern int use_privsep;
+extern Buffer cfg;
/* Initializes the server options to their default values. */
@@ -100,9 +102,6 @@ initialize_server_options(ServerOptions *options)
options->authorized_keys_file2 = NULL;
options->num_accept_env = 0;
options->permit_tun = -1;
-
- /* Needs to be accessable in many places */
- use_privsep = -1;
}
void
@@ -254,98 +253,105 @@ typedef enum {
sHostbasedUsesNameFromPacketOnly, sClientAliveInterval,
sClientAliveCountMax, sAuthorizedKeysFile, sAuthorizedKeysFile2,
sGssAuthentication, sGssCleanupCreds, sAcceptEnv, sPermitTunnel,
+ sMatch,
sUsePrivilegeSeparation,
sDeprecated, sUnsupported
} ServerOpCodes;
+#define SSHCFG_GLOBAL 0x01 /* allowed in main section of sshd_config */
+#define SSHCFG_MATCH 0x02 /* allowed inside a Match section */
+#define SSHCFG_ALL (SSHCFG_GLOBAL|SSHCFG_MATCH)
+
/* Textual representation of the tokens. */
static struct {
const char *name;
ServerOpCodes opcode;
+ u_int flags;
} keywords[] = {
- { "port", sPort },
- { "hostkey", sHostKeyFile },
- { "hostdsakey", sHostKeyFile }, /* alias */
- { "pidfile", sPidFile },
- { "serverkeybits", sServerKeyBits },
- { "logingracetime", sLoginGraceTime },
- { "keyregenerationinterval", sKeyRegenerationTime },
- { "permitrootlogin", sPermitRootLogin },
- { "syslogfacility", sLogFacility },
- { "loglevel", sLogLevel },
- { "rhostsauthentication", sDeprecated },
- { "rhostsrsaauthentication", sRhostsRSAAuthentication },
- { "hostbasedauthentication", sHostbasedAuthentication },
- { "hostbasedusesnamefrompacketonly", sHostbasedUsesNameFromPacketOnly },
- { "rsaauthentication", sRSAAuthentication },
- { "pubkeyauthentication", sPubkeyAuthentication },
- { "dsaauthentication", sPubkeyAuthentication }, /* alias */
+ { "port", sPort, SSHCFG_GLOBAL },
+ { "hostkey", sHostKeyFile, SSHCFG_GLOBAL },
+ { "hostdsakey", sHostKeyFile, SSHCFG_GLOBAL }, /* alias */
+ { "pidfile", sPidFile, SSHCFG_GLOBAL },
+ { "serverkeybits", sServerKeyBits, SSHCFG_GLOBAL },
+ { "logingracetime", sLoginGraceTime, SSHCFG_GLOBAL },
+ { "keyregenerationinterval", sKeyRegenerationTime, SSHCFG_GLOBAL },
+ { "permitrootlogin", sPermitRootLogin, SSHCFG_GLOBAL },
+ { "syslogfacility", sLogFacility, SSHCFG_GLOBAL },
+ { "loglevel", sLogLevel, SSHCFG_GLOBAL },
+ { "rhostsauthentication", sDeprecated, SSHCFG_GLOBAL },
+ { "rhostsrsaauthentication", sRhostsRSAAuthentication, SSHCFG_GLOBAL },
+ { "hostbasedauthentication", sHostbasedAuthentication, SSHCFG_GLOBAL },
+ { "hostbasedusesnamefrompacketonly", sHostbasedUsesNameFromPacketOnly, SSHCFG_GLOBAL },
+ { "rsaauthentication", sRSAAuthentication, SSHCFG_GLOBAL },
+ { "pubkeyauthentication", sPubkeyAuthentication, SSHCFG_GLOBAL },
+ { "dsaauthentication", sPubkeyAuthentication, SSHCFG_GLOBAL }, /* alias */
#ifdef KRB5
- { "kerberosauthentication", sKerberosAuthentication },
- { "kerberosorlocalpasswd", sKerberosOrLocalPasswd },
- { "kerberosticketcleanup", sKerberosTicketCleanup },
- { "kerberosgetafstoken", sKerberosGetAFSToken },
+ { "kerberosauthentication", sKerberosAuthentication, SSHCFG_GLOBAL },
+ { "kerberosorlocalpasswd", sKerberosOrLocalPasswd, SSHCFG_GLOBAL },
+ { "kerberosticketcleanup", sKerberosTicketCleanup, SSHCFG_GLOBAL },
+ { "kerberosgetafstoken", sKerberosGetAFSToken, SSHCFG_GLOBAL },
#else
- { "kerberosauthentication", sUnsupported },
- { "kerberosorlocalpasswd", sUnsupported },
- { "kerberosticketcleanup", sUnsupported },
- { "kerberosgetafstoken", sUnsupported },
+ { "kerberosauthentication", sUnsupported, SSHCFG_GLOBAL },
+ { "kerberosorlocalpasswd", sUnsupported, SSHCFG_GLOBAL },
+ { "kerberosticketcleanup", sUnsupported, SSHCFG_GLOBAL },
+ { "kerberosgetafstoken", sUnsupported, SSHCFG_GLOBAL },
#endif
- { "kerberostgtpassing", sUnsupported },
- { "afstokenpassing", sUnsupported },
+ { "kerberostgtpassing", sUnsupported, SSHCFG_GLOBAL },
+ { "afstokenpassing", sUnsupported, SSHCFG_GLOBAL },
#ifdef GSSAPI
- { "gssapiauthentication", sGssAuthentication },
- { "gssapicleanupcredentials", sGssCleanupCreds },
+ { "gssapiauthentication", sGssAuthentication, SSHCFG_GLOBAL },
+ { "gssapicleanupcredentials", sGssCleanupCreds, SSHCFG_GLOBAL },
#else
- { "gssapiauthentication", sUnsupported },
- { "gssapicleanupcredentials", sUnsupported },
+ { "gssapiauthentication", sUnsupported, SSHCFG_GLOBAL },
+ { "gssapicleanupcredentials", sUnsupported, SSHCFG_GLOBAL },
#endif
- { "passwordauthentication", sPasswordAuthentication },
- { "kbdinteractiveauthentication", sKbdInteractiveAuthentication },
- { "challengeresponseauthentication", sChallengeResponseAuthentication },
- { "skeyauthentication", sChallengeResponseAuthentication }, /* alias */
- { "checkmail", sDeprecated },
- { "listenaddress", sListenAddress },
- { "addressfamily", sAddressFamily },
- { "printmotd", sPrintMotd },
- { "printlastlog", sPrintLastLog },
- { "ignorerhosts", sIgnoreRhosts },
- { "ignoreuserknownhosts", sIgnoreUserKnownHosts },
- { "x11forwarding", sX11Forwarding },
- { "x11displayoffset", sX11DisplayOffset },
- { "x11uselocalhost", sX11UseLocalhost },
- { "xauthlocation", sXAuthLocation },
- { "strictmodes", sStrictModes },
- { "permitemptypasswords", sEmptyPasswd },
- { "permituserenvironment", sPermitUserEnvironment },
- { "uselogin", sUseLogin },
- { "compression", sCompression },
- { "tcpkeepalive", sTCPKeepAlive },
- { "keepalive", sTCPKeepAlive }, /* obsolete alias */
- { "allowtcpforwarding", sAllowTcpForwarding },
- { "allowusers", sAllowUsers },
- { "denyusers", sDenyUsers },
- { "allowgroups", sAllowGroups },
- { "denygroups", sDenyGroups },
- { "ciphers", sCiphers },
- { "macs", sMacs },
- { "protocol", sProtocol },
- { "gatewayports", sGatewayPorts },
- { "subsystem", sSubsystem },
- { "maxstartups", sMaxStartups },
- { "maxauthtries", sMaxAuthTries },
- { "banner", sBanner },
- { "usedns", sUseDNS },
- { "verifyreversemapping", sDeprecated },
- { "reversemappingcheck", sDeprecated },
- { "clientaliveinterval", sClientAliveInterval },
- { "clientalivecountmax", sClientAliveCountMax },
- { "authorizedkeysfile", sAuthorizedKeysFile },
- { "authorizedkeysfile2", sAuthorizedKeysFile2 },
- { "useprivilegeseparation", sUsePrivilegeSeparation},
- { "acceptenv", sAcceptEnv },
- { "permittunnel", sPermitTunnel },
- { NULL, sBadOption }
+ { "passwordauthentication", sPasswordAuthentication, SSHCFG_GLOBAL },
+ { "kbdinteractiveauthentication", sKbdInteractiveAuthentication, SSHCFG_GLOBAL },
+ { "challengeresponseauthentication", sChallengeResponseAuthentication, SSHCFG_GLOBAL },
+ { "skeyauthentication", sChallengeResponseAuthentication, SSHCFG_GLOBAL }, /* alias */
+ { "checkmail", sDeprecated, SSHCFG_GLOBAL },
+ { "listenaddress", sListenAddress, SSHCFG_GLOBAL },
+ { "addressfamily", sAddressFamily, SSHCFG_GLOBAL },
+ { "printmotd", sPrintMotd, SSHCFG_GLOBAL },
+ { "printlastlog", sPrintLastLog, SSHCFG_GLOBAL },
+ { "ignorerhosts", sIgnoreRhosts, SSHCFG_GLOBAL },
+ { "ignoreuserknownhosts", sIgnoreUserKnownHosts, SSHCFG_GLOBAL },
+ { "x11forwarding", sX11Forwarding, SSHCFG_GLOBAL },
+ { "x11displayoffset", sX11DisplayOffset, SSHCFG_GLOBAL },
+ { "x11uselocalhost", sX11UseLocalhost, SSHCFG_GLOBAL },
+ { "xauthlocation", sXAuthLocation, SSHCFG_GLOBAL },
+ { "strictmodes", sStrictModes, SSHCFG_GLOBAL },
+ { "permitemptypasswords", sEmptyPasswd, SSHCFG_GLOBAL },
+ { "permituserenvironment", sPermitUserEnvironment, SSHCFG_GLOBAL },
+ { "uselogin", sUseLogin, SSHCFG_GLOBAL },
+ { "compression", sCompression, SSHCFG_GLOBAL },
+ { "tcpkeepalive", sTCPKeepAlive, SSHCFG_GLOBAL },
+ { "keepalive", sTCPKeepAlive, SSHCFG_GLOBAL }, /* obsolete alias */
+ { "allowtcpforwarding", sAllowTcpForwarding, SSHCFG_ALL },
+ { "allowusers", sAllowUsers, SSHCFG_GLOBAL },
+ { "denyusers", sDenyUsers, SSHCFG_GLOBAL },
+ { "allowgroups", sAllowGroups, SSHCFG_GLOBAL },
+ { "denygroups", sDenyGroups, SSHCFG_GLOBAL },
+ { "ciphers", sCiphers, SSHCFG_GLOBAL },
+ { "macs", sMacs, SSHCFG_GLOBAL },
+ { "protocol", sProtocol, SSHCFG_GLOBAL },
+ { "gatewayports", sGatewayPorts, SSHCFG_ALL },
+ { "subsystem", sSubsystem, SSHCFG_GLOBAL },
+ { "maxstartups", sMaxStartups, SSHCFG_GLOBAL },
+ { "maxauthtries", sMaxAuthTries, SSHCFG_GLOBAL },
+ { "banner", sBanner, SSHCFG_GLOBAL },
+ { "usedns", sUseDNS, SSHCFG_GLOBAL },
+ { "verifyreversemapping", sDeprecated, SSHCFG_GLOBAL },
+ { "reversemappingcheck", sDeprecated, SSHCFG_GLOBAL },
+ { "clientaliveinterval", sClientAliveInterval, SSHCFG_GLOBAL },
+ { "clientalivecountmax", sClientAliveCountMax, SSHCFG_GLOBAL },
+ { "authorizedkeysfile", sAuthorizedKeysFile, SSHCFG_GLOBAL },
+ { "authorizedkeysfile2", sAuthorizedKeysFile2, SSHCFG_GLOBAL },
+ { "useprivilegeseparation", sUsePrivilegeSeparation, SSHCFG_GLOBAL},
+ { "acceptenv", sAcceptEnv, SSHCFG_GLOBAL },
+ { "permittunnel", sPermitTunnel, SSHCFG_GLOBAL },
+ { "match", sMatch, SSHCFG_ALL },
+ { NULL, sBadOption, 0 }
};
/*
@@ -354,13 +360,15 @@ static struct {
static ServerOpCodes
parse_token(const char *cp, const char *filename,
- int linenum)
+ int linenum, u_int *flags)
{
u_int i;
for (i = 0; keywords[i].name; i++)
- if (strcasecmp(cp, keywords[i].name) == 0)
+ if (strcasecmp(cp, keywords[i].name) == 0) {
+ *flags = keywords[i].flags;
return keywords[i].opcode;
+ }
error("%s: line %d: Bad configuration option: %s",
filename, linenum, cp);
@@ -405,15 +413,112 @@ add_one_listen_addr(ServerOptions *options, char *addr, u_short port)
options->listen_addrs = aitop;
}
+/*
+ * The strategy for the Match blocks is that the config file is parsed twice.
+ *
+ * The first time is at startup. activep is initialized to 1 and the
+ * directives in the global context are processed and acted on. Hitting a
+ * Match directive unsets activep and the directives inside the block are
+ * checked for syntax only.
+ *
+ * The second time is after a connection has been established but before
+ * authentication. activep is initialized to 2 and global config directives
+ * are ignored since they have already been processed. If the criteria in a
+ * Match block is met, activep is set and the subsequent directives
+ * processed and actioned until EOF or another Match block unsets it. Any
+ * options set are copied into the main server config.
+ *
+ * Potential additions/improvements:
+ * - Add Match support for pre-kex directives, eg Protocol, Ciphers.
+ *
+ * - Add a Tag directive (idea from David Leonard) ala pf, eg:
+ * Match Address 192.168.0.*
+ * Tag trusted
+ * Match Group wheel
+ * Tag trusted
+ * Match Tag trusted
+ * AllowTcpForwarding yes
+ * GatewayPorts clientspecified
+ * [...]
+ *
+ * - Add a PermittedChannelRequests directive
+ * Match Group shell
+ * PermittedChannelRequests session,forwarded-tcpip
+ */
+
+static int
+match_cfg_line(char **condition, int line, const char *user, const char *host,
+ const char *address)
+{
+ int result = 1;
+ char *arg, *attrib, *cp = *condition;
+ size_t len;
+
+ if (user == NULL)
+ debug3("checking syntax for 'Match %s'", cp);
+ else
+ debug3("checking match for '%s' user %s host %s addr %s", cp,
+ user ? user : "(null)", host ? host : "(null)",
+ address ? address : "(null)");
+
+ while ((attrib = strdelim(&cp)) && *attrib != '\0') {
+ if ((arg = strdelim(&cp)) == NULL || *arg == '\0') {
+ error("Missing Match criteria for %s", attrib);
+ return -1;
+ }
+ len = strlen(arg);
+ if (strcasecmp(attrib, "user") == 0) {
+ if (!user) {
+ result = 0;
+ continue;
+ }
+ if (match_pattern_list(user, arg, len, 0) != 1)
+ result = 0;
+ else
+ debug("user %.100s matched 'User %.100s' at "
+ "line %d", user, arg, line);
+ } else if (strcasecmp(attrib, "host") == 0) {
+ if (!host) {
+ result = 0;
+ continue;
+ }
+ if (match_hostname(host, arg, len) != 1)
+ result = 0;
+ else
+ debug("connection from %.100s matched 'Host "
+ "%.100s' at line %d", host, arg, line);
+ } else if (strcasecmp(attrib, "address") == 0) {
+ debug("address '%s' arg '%s'", address, arg);
+ if (!address) {
+ result = 0;
+ continue;
+ }
+ if (match_hostname(address, arg, len) != 1)
+ result = 0;
+ else
+ debug("connection from %.100s matched 'Address "
+ "%.100s' at line %d", address, arg, line);
+ } else {
+ error("Unsupported Match attribute %s", attrib);
+ return -1;
+ }
+ }
+ if (user != NULL)
+ debug3("match %sfound", result ? "" : "not ");
+ *condition = cp;
+ return result;
+}
+
int
process_server_config_line(ServerOptions *options, char *line,
- const char *filename, int linenum)
+ const char *filename, int linenum, int *activep, const char *user,
+ const char *host, const char *address)
{
char *cp, **charptr, *arg, *p;
- int *intptr, value, n;
+ int cmdline = 0, *intptr, value, n;
ServerOpCodes opcode;
u_short port;
- u_int i;
+ u_int i, flags = 0;
size_t len;
cp = line;
@@ -426,7 +531,25 @@ process_server_config_line(ServerOptions *options, char *line,
return 0;
intptr = NULL;
charptr = NULL;
- opcode = parse_token(arg, filename, linenum);
+ opcode = parse_token(arg, filename, linenum, &flags);
+
+ if (activep == NULL) { /* We are processing a command line directive */
+ cmdline = 1;
+ activep = &cmdline;
+ }
+ if (*activep && opcode != sMatch)
+ debug3("%s:%d setting %s %s", filename, linenum, arg, cp);
+ if (*activep == 0 && !(flags & SSHCFG_MATCH)) {
+ if (user == NULL) {
+ fatal("%s line %d: Directive '%s' is not allowed "
+ "within a Match block", filename, linenum, arg);
+ } else { /* this is a directive we have already processed */
+ while (arg)
+ arg = strdelim(&cp);
+ return 0;
+ }
+ }
+
switch (opcode) {
case sBadOption:
return -1;
@@ -458,7 +581,7 @@ parse_int:
fatal("%s line %d: missing integer value.",
filename, linenum);
value = atoi(arg);
- if (*intptr == -1)
+ if (*activep && *intptr == -1)
*intptr = value;
break;
@@ -538,7 +661,7 @@ parse_filename:
if (!arg || *arg == '\0')
fatal("%s line %d: missing file name.",
filename, linenum);
- if (*charptr == NULL) {
+ if (*activep && *charptr == NULL) {
*charptr = tilde_expand_filename(arg, getuid());
/* increase optional counter */
if (intptr != NULL)
@@ -589,7 +712,7 @@ parse_flag:
else
fatal("%s line %d: Bad yes/no argument: %s",
filename, linenum, arg);
- if (*intptr == -1)
+ if (*activep && *intptr == -1)
*intptr = value;
break;
@@ -854,6 +977,10 @@ parse_flag:
if (!arg || *arg == '\0')
fatal("%s line %d: Missing subsystem name.",
filename, linenum);
+ if (!*activep) {
+ arg = strdelim(&cp);
+ break;
+ }
for (i = 0; i < options->num_subsystems; i++)
if (strcmp(arg, options->subsystem_name[i]) == 0)
fatal("%s line %d: Subsystem '%s' already defined.",
@@ -936,6 +1063,8 @@ parse_flag:
if (options->num_accept_env >= MAX_ACCEPT_ENV)
fatal("%s line %d: too many allow env.",
filename, linenum);
+ if (!*activep)
+ break;
options->accept_env[options->num_accept_env++] =
xstrdup(arg);
}
@@ -963,6 +1092,17 @@ parse_flag:
*intptr = value;
break;
+ case sMatch:
+ if (cmdline)
+ fatal("Match directive not supported as a command-line "
+ "option");
+ value = match_cfg_line(&cp, linenum, user, host, address);
+ if (value < 0)
+ fatal("%s line %d: Bad Match condition", filename,
+ linenum);
+ *activep = value;
+ break;
+
case sDeprecated:
logit("%s line %d: Deprecated option %s",
filename, linenum, arg);
@@ -1019,18 +1159,41 @@ load_server_config(const char *filename, Buffer *conf)
}
void
-parse_server_config(ServerOptions *options, const char *filename, Buffer *conf)
+parse_server_match_config(ServerOptions *options, const char *user,
+ const char *host, const char *address)
+{
+ ServerOptions mo;
+
+ initialize_server_options(&mo);
+ parse_server_config(&mo, "reprocess config", &cfg, user, host, address);
+ copy_set_server_options(options, &mo);
+}
+
+/* Copy any (supported) values that are set */
+void
+copy_set_server_options(ServerOptions *dst, ServerOptions *src)
+{
+ if (src->allow_tcp_forwarding != -1)
+ dst->allow_tcp_forwarding = src->allow_tcp_forwarding;
+ if (src->gateway_ports != -1)
+ dst->gateway_ports = src->gateway_ports;
+}
+
+void
+parse_server_config(ServerOptions *options, const char *filename, Buffer *conf,
+ const char *user, const char *host, const char *address)
{
- int linenum, bad_options = 0;
+ int active, linenum, bad_options = 0;
char *cp, *obuf, *cbuf;
debug2("%s: config %s len %d", __func__, filename, buffer_len(conf));
obuf = cbuf = xstrdup(buffer_ptr(conf));
+ active = user ? 0 : 1;
linenum = 1;
while ((cp = strsep(&cbuf, "\n")) != NULL) {
if (process_server_config_line(options, cp, filename,
- linenum++) != 0)
+ linenum++, &active, user, host, address) != 0)
bad_options++;
}
xfree(obuf);
diff --git a/usr.bin/ssh/servconf.h b/usr.bin/ssh/servconf.h
index 5152e936c7f..233790d29c5 100644
--- a/usr.bin/ssh/servconf.h
+++ b/usr.bin/ssh/servconf.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: servconf.h,v 1.74 2006/07/06 10:47:05 djm Exp $ */
+/* $OpenBSD: servconf.h,v 1.75 2006/07/12 11:34:58 dtucker Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
@@ -140,8 +140,13 @@ typedef struct {
void initialize_server_options(ServerOptions *);
void fill_default_server_options(ServerOptions *);
-int process_server_config_line(ServerOptions *, char *, const char *, int);
+int process_server_config_line(ServerOptions *, char *, const char *, int,
+ int *, const char *, const char *, const char *);
void load_server_config(const char *, Buffer *);
-void parse_server_config(ServerOptions *, const char *, Buffer *);
+void parse_server_config(ServerOptions *, const char *, Buffer *,
+ const char *, const char *, const char *);
+void parse_server_match_config(ServerOptions *, const char *, const char *,
+ const char *);
+void copy_set_server_options(ServerOptions *, ServerOptions *);
#endif /* SERVCONF_H */
diff --git a/usr.bin/ssh/sshd.c b/usr.bin/ssh/sshd.c
index 6e0e20ee264..fdd9475f0dd 100644
--- a/usr.bin/ssh/sshd.c
+++ b/usr.bin/ssh/sshd.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: sshd.c,v 1.336 2006/07/11 20:07:25 stevesk Exp $ */
+/* $OpenBSD: sshd.c,v 1.337 2006/07/12 11:34:58 dtucker Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -209,12 +209,15 @@ int *startup_pipes = NULL;
int startup_pipe; /* in child */
/* variables used for privilege separation */
-int use_privsep;
+int use_privsep = -1;
struct monitor *pmonitor = NULL;
/* global authentication context */
Authctxt *the_authctxt = NULL;
+/* sshd_config buffer */
+Buffer cfg;
+
/* message to be displayed after login */
Buffer loginmsg;
@@ -892,7 +895,6 @@ main(int ac, char **av)
Key *key;
Authctxt *authctxt;
int ret, key_used = 0;
- Buffer cfg;
/* Save argv. */
saved_argv = av;
@@ -993,7 +995,7 @@ main(int ac, char **av)
case 'o':
line = xstrdup(optarg);
if (process_server_config_line(&options, line,
- "command-line", 0) != 0)
+ "command-line", 0, NULL, NULL, NULL, NULL) != 0)
exit(1);
xfree(line);
break;
@@ -1037,11 +1039,8 @@ main(int ac, char **av)
else
load_server_config(config_file_name, &cfg);
- parse_server_config(&options,
- rexeced_flag ? "rexec" : config_file_name, &cfg);
-
- if (!rexec_flag)
- buffer_free(&cfg);
+ parse_server_config(&options, rexeced_flag ? "rexec" : config_file_name,
+ &cfg, NULL, NULL, NULL);
/* Fill in default values for those options not explicitly set. */
fill_default_server_options(&options);
diff --git a/usr.bin/ssh/sshd_config.5 b/usr.bin/ssh/sshd_config.5
index 20260d94efe..941f2724b66 100644
--- a/usr.bin/ssh/sshd_config.5
+++ b/usr.bin/ssh/sshd_config.5
@@ -34,7 +34,7 @@
.\" (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: sshd_config.5,v 1.59 2006/07/06 10:47:05 djm Exp $
+.\" $OpenBSD: sshd_config.5,v 1.60 2006/07/12 11:34:58 dtucker Exp $
.Dd September 25, 1999
.Dt SSHD_CONFIG 5
.Os
@@ -463,6 +463,27 @@ for data integrity protection.
Multiple algorithms must be comma-separated.
The default is:
.Dq hmac-md5,hmac-sha1,hmac-ripemd160,hmac-sha1-96,hmac-md5-96 .
+.It Cm Match
+Introduces a conditional block. Keywords on lines following a
+.Cm Match
+block are only applied if all of the criteria on the
+.Cm Match
+are satisfied.
+The the arguments to
+.Cm Match
+block are one or more criteria-pattern pairs.
+The available criteria are
+.Cm User ,
+.Cm Host ,
+and
+.Cm Address .
+Only a subset of keywords may be used on the lines following a
+.Cm Match
+keyword.
+Available keywords are
+.Cm AllowTcpForwarding ,
+and
+.Cm GatewayPorts .
.It Cm MaxAuthTries
Specifies the maximum number of authentication attempts permitted per
connection.