sshd config parser
Darren Tucker
dtucker at zip.com.au
Sun Apr 2 12:43:30 EST 2006
Hi All.
Here's an updated patch. It's not actually as big as it looks as nearly
half of it as adding a flag to the keyword struct and large comment.
The supported Match directives are User, Group, Host and Address.
The directives supported inside a Match block are:
UsePAM, LoginGraceTime, PermitRootLogin, LogFacility,
LogLevel, RhostsRSAAuthentication, HostbasedAuthentication,
HostbasedUsesNameFromPacketOnly, RSAAuthentication, PubkeyAuthentication,
PubkeyAuthentication, KerberosAuthentication, KerberosOrLocalPasswd,
KerberosTicketCleanup, KerberosGetAFSToken, GssAuthentication,
GssCleanupCreds, PasswordAuthentication, KbdInteractiveAuthentication,
ChallengeResponseAuthentication, ChallengeResponseAuthentication,
PrintMotd, PrintLastLog, IgnoreRhosts, IgnoreUserKnownHosts,
X11Forwarding, X11DisplayOffset, X11UseLocalhost, XAuthLocation,
StrictModes, PermitEmptyPasswd, PermitUserEnvironment, UseLogin,
AllowTcpForwarding, GatewayPorts, MaxAuthTries, Banner,
ClientAliveInterval, ClientAliveCountMax, AuthorizedKeysFile,
AuthorizedKeysFile2, AcceptEnv, PermitTunnel
(not all of those are tested, though)
It seems to have some decent potential:
# Password is OK from the local net but not from the Net
PasswordAuthentication no
Match 192.168.0.*
PasswordAuthentication yes
# Only trusted users can use forwarding
AllowTcpForwarding no
Match Group fwd
AllowTcpForwarding yes
GatewayPorts clientspecified
--
Darren Tucker (dtucker at zip.com.au)
GPG key 8FF4FA69 / D9A3 86E9 7EEE AF4B B2D4 37C9 C982 80C7 8FF4 FA69
Good judgement comes with experience. Unfortunately, the experience
usually comes from bad judgement.
-------------- next part --------------
Index: auth.c
===================================================================
RCS file: /usr/local/src/security/openssh/cvs/openssh_cvs/auth.c,v
retrieving revision 1.101
diff -u -p -r1.101 auth.c
--- auth.c 31 Aug 2005 16:59:49 -0000 1.101
+++ auth.c 2 Apr 2006 02:23:02 -0000
@@ -492,6 +492,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",
Index: match.c
===================================================================
RCS file: /usr/local/src/security/openssh/cvs/openssh_cvs/match.c,v
retrieving revision 1.19
diff -u -p -r1.19 match.c
--- match.c 17 Jun 2005 02:59:35 -0000 1.19
+++ match.c 2 Apr 2006 02:20:16 -0000
@@ -39,6 +39,10 @@ RCSID("$OpenBSD: match.c,v 1.20 2005/06/
#include "match.h"
#include "xmalloc.h"
+#include "log.h"
+#include "misc.h"
+#include "canohost.h"
+#include "groupaccess.h"
/*
* Returns true if the given string matches the pattern (which may contain ?
@@ -267,3 +271,89 @@ match_list(const char *client, const cha
xfree(s);
return NULL;
}
+
+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, *grplist[1];
+ size_t len;
+ struct passwd *pw;
+
+ if (user == NULL)
+ debug3("checking syntax for 'Match %s'", cp);
+ else
+ debug3("checking match for '%s'", cp);
+
+ 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)
+ /* XXX what about negative match? */
+ result = 0;
+ else
+ debug("user %.100s matched 'User %.100s' at "
+ "line %d", user, arg, line);
+ } else if (strcasecmp(attrib, "group") == 0) {
+ if (!user) {
+ result = 0;
+ continue;
+ }
+ grplist[0] = arg; /* XXX split on comma */
+ if ((pw = getpwnam(user)) == NULL) {
+ debug("Can't match group at line %d because "
+ "user %.100s does not exist", line, user);
+ result = 0;
+ } else if (ga_init(pw->pw_name, pw->pw_gid) == 0) {
+ debug("Can't Match group because user %.100s "
+ "not in any group at line %d", user,
+ line);
+ result = 0;
+ } else if (ga_match(grplist, 1) != 1) {
+ debug("User %.100s does not match group "
+ "%.100s at line %d", user, arg,
+ line);
+ result = 0;
+ } else {
+ debug("User %.100s matched Group %.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) {
+ debug3("%s: address %s", __func__, address);
+ 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;
+ }
+ }
+ *condition = cp;
+ debug3("match_cfg_line: returning %d", result);
+ return result;
+}
Index: match.h
===================================================================
RCS file: /usr/local/src/security/openssh/cvs/openssh_cvs/match.h,v
retrieving revision 1.11
diff -u -p -r1.11 match.h
--- match.h 5 Mar 2002 01:42:43 -0000 1.11
+++ match.h 2 Apr 2006 01:27:11 -0000
@@ -20,5 +20,6 @@ int match_hostname(const char *, const
int match_host_and_ip(const char *, const char *, const char *);
int match_user(const char *, const char *, const char *, const char *);
char *match_list(const char *, const char *, u_int *);
+int match_cfg_line(char **, int, const char *, const char *, const char *);
#endif
Index: monitor.c
===================================================================
RCS file: /usr/local/src/security/openssh/cvs/openssh_cvs/monitor.c,v
retrieving revision 1.88
diff -u -p -r1.88 monitor.c
--- monitor.c 5 Nov 2005 04:07:05 -0000 1.88
+++ monitor.c 2 Apr 2006 01:08:28 -0000
@@ -612,6 +612,7 @@ mm_answer_pwnamallow(int sock, Buffer *m
#endif
buffer_put_cstring(m, pwent->pw_dir);
buffer_put_cstring(m, pwent->pw_shell);
+ buffer_put_string(m, &options, sizeof(options));
out:
debug3("%s: sending MONITOR_ANS_PWNAM: %d", __func__, allowed);
Index: monitor_wrap.c
===================================================================
RCS file: /usr/local/src/security/openssh/cvs/openssh_cvs/monitor_wrap.c,v
retrieving revision 1.54
diff -u -p -r1.54 monitor_wrap.c
--- monitor_wrap.c 29 Sep 2005 12:01:10 -0000 1.54
+++ monitor_wrap.c 2 Apr 2006 01:45:05 -0000
@@ -196,7 +196,8 @@ mm_getpwnamallow(const char *username)
{
Buffer m;
struct passwd *pw;
- u_int pwlen;
+ u_int len;
+ void *p;
debug3("%s entering", __func__);
@@ -212,8 +213,8 @@ mm_getpwnamallow(const char *username)
buffer_free(&m);
return (NULL);
}
- pw = buffer_get_string(&m, &pwlen);
- if (pwlen != sizeof(struct passwd))
+ pw = buffer_get_string(&m, &len);
+ if (len != sizeof(struct passwd))
fatal("%s: struct passwd size mismatch", __func__);
pw->pw_name = buffer_get_string(&m, NULL);
pw->pw_passwd = buffer_get_string(&m, NULL);
@@ -223,6 +224,10 @@ mm_getpwnamallow(const char *username)
#endif
pw->pw_dir = buffer_get_string(&m, NULL);
pw->pw_shell = buffer_get_string(&m, NULL);
+ p = buffer_get_string(&m, &len);
+ if (len != sizeof(options))
+ fatal("%s: option block size mismatch", __func__);
+ memcpy(&options, p, len);
buffer_free(&m);
return (pw);
Index: servconf.c
===================================================================
RCS file: /usr/local/src/security/openssh/cvs/openssh_cvs/servconf.c,v
retrieving revision 1.136
diff -u -p -r1.136 servconf.c
--- servconf.c 13 Dec 2005 08:33:20 -0000 1.136
+++ servconf.c 2 Apr 2006 02:14:03 -0000
@@ -22,12 +22,14 @@ RCSID("$OpenBSD: servconf.c,v 1.146 2005
#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. */
@@ -102,9 +104,6 @@ initialize_server_options(ServerOptions
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
@@ -274,110 +273,121 @@ typedef enum {
sHostbasedUsesNameFromPacketOnly, sClientAliveInterval,
sClientAliveCountMax, sAuthorizedKeysFile, sAuthorizedKeysFile2,
sGssAuthentication, sGssCleanupCreds, sAcceptEnv, sPermitTunnel,
+ sMatch,
sUsePrivilegeSeparation,
sDeprecated, sUnsupported
} ServerOpCodes;
+#define SSHCFG_GLOBAL 0x01
+#define SSHCFG_MATCH 0x02
+#define SSHCFG_ALL (SSHCFG_GLOBAL|SSHCFG_MATCH)
+
/* Textual representation of the tokens. */
static struct {
const char *name;
ServerOpCodes opcode;
+ u_int flags;
} keywords[] = {
/* Portable-specific options */
#ifdef USE_PAM
- { "usepam", sUsePAM },
+ { "usepam", sUsePAM, SSHCFG_ALL },
#else
- { "usepam", sUnsupported },
+ { "usepam", sUnsupported, SSHCFG_ALL },
#endif
- { "pamauthenticationviakbdint", sDeprecated },
+ { "pamauthenticationviakbdint", sDeprecated, SSHCFG_GLOBAL },
/* Standard Options */
- { "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_ALL },
+ { "keyregenerationinterval", sKeyRegenerationTime, SSHCFG_GLOBAL },
+ { "permitrootlogin", sPermitRootLogin, SSHCFG_ALL },
+ { "syslogfacility", sLogFacility, SSHCFG_ALL },
+ { "loglevel", sLogLevel, SSHCFG_ALL },
+ { "rhostsauthentication", sDeprecated, SSHCFG_GLOBAL },
+ { "rhostsrsaauthentication", sRhostsRSAAuthentication, SSHCFG_ALL },
+ { "hostbasedauthentication", sHostbasedAuthentication, SSHCFG_ALL },
+ { "hostbasedusesnamefrompacketonly", sHostbasedUsesNameFromPacketOnly,
+ SSHCFG_ALL },
+ { "rsaauthentication", sRSAAuthentication, SSHCFG_ALL },
+ { "pubkeyauthentication", sPubkeyAuthentication, SSHCFG_ALL },
+ { "dsaauthentication", sPubkeyAuthentication, SSHCFG_ALL }, /* alias */
#ifdef KRB5
- { "kerberosauthentication", sKerberosAuthentication },
- { "kerberosorlocalpasswd", sKerberosOrLocalPasswd },
- { "kerberosticketcleanup", sKerberosTicketCleanup },
+ { "kerberosauthentication", sKerberosAuthentication, SSHCFG_ALL },
+ { "kerberosorlocalpasswd", sKerberosOrLocalPasswd, SSHCFG_ALL },
+ { "kerberosticketcleanup", sKerberosTicketCleanup, SSHCFG_ALL },
#ifdef USE_AFS
- { "kerberosgetafstoken", sKerberosGetAFSToken },
+ { "kerberosgetafstoken", sKerberosGetAFSToken, SSHCFG_ALL },
#else
- { "kerberosgetafstoken", sUnsupported },
+ { "kerberosgetafstoken", sUnsupported, SSHCFG_ALL },
#endif
#else
- { "kerberosauthentication", sUnsupported },
- { "kerberosorlocalpasswd", sUnsupported },
- { "kerberosticketcleanup", sUnsupported },
- { "kerberosgetafstoken", sUnsupported },
+ { "kerberosauthentication", sUnsupported, SSHCFG_ALL },
+ { "kerberosorlocalpasswd", sUnsupported, SSHCFG_ALL },
+ { "kerberosticketcleanup", sUnsupported, SSHCFG_ALL },
+ { "kerberosgetafstoken", sUnsupported, SSHCFG_ALL },
#endif
- { "kerberostgtpassing", sUnsupported },
- { "afstokenpassing", sUnsupported },
+ { "kerberostgtpassing", sUnsupported, SSHCFG_ALL },
+ { "afstokenpassing", sUnsupported, SSHCFG_ALL },
#ifdef GSSAPI
- { "gssapiauthentication", sGssAuthentication },
- { "gssapicleanupcredentials", sGssCleanupCreds },
+ { "gssapiauthentication", sGssAuthentication, SSHCFG_ALL },
+ { "gssapicleanupcredentials", sGssCleanupCreds, SSHCFG_ALL },
#else
- { "gssapiauthentication", sUnsupported },
- { "gssapicleanupcredentials", sUnsupported },
+ { "gssapiauthentication", sUnsupported, SSHCFG_ALL },
+ { "gssapicleanupcredentials", sUnsupported, SSHCFG_ALL },
#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_ALL },
+ { "kbdinteractiveauthentication", sKbdInteractiveAuthentication,
+ SSHCFG_ALL },
+ { "challengeresponseauthentication", sChallengeResponseAuthentication,
+ SSHCFG_ALL },
+ { "skeyauthentication", sChallengeResponseAuthentication,
+ SSHCFG_ALL }, /* alias */
+ { "checkmail", sDeprecated, SSHCFG_GLOBAL },
+ { "listenaddress", sListenAddress, SSHCFG_GLOBAL },
+ { "addressfamily", sAddressFamily, SSHCFG_GLOBAL },
+ { "printmotd", sPrintMotd, SSHCFG_ALL },
+ { "printlastlog", sPrintLastLog, SSHCFG_ALL },
+ { "ignorerhosts", sIgnoreRhosts, SSHCFG_ALL },
+ { "ignoreuserknownhosts", sIgnoreUserKnownHosts, SSHCFG_ALL },
+ { "x11forwarding", sX11Forwarding, SSHCFG_ALL },
+ { "x11displayoffset", sX11DisplayOffset, SSHCFG_ALL },
+ { "x11uselocalhost", sX11UseLocalhost, SSHCFG_ALL },
+ { "xauthlocation", sXAuthLocation, SSHCFG_ALL },
+ { "strictmodes", sStrictModes, SSHCFG_ALL },
+ { "permitemptypasswords", sEmptyPasswd, SSHCFG_ALL },
+ { "permituserenvironment", sPermitUserEnvironment, SSHCFG_ALL },
+ { "uselogin", sUseLogin, SSHCFG_ALL },
+ { "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_ALL },
+ { "banner", sBanner, SSHCFG_ALL },
+ { "usedns", sUseDNS, SSHCFG_GLOBAL },
+ { "verifyreversemapping", sDeprecated, SSHCFG_GLOBAL },
+ { "reversemappingcheck", sDeprecated, SSHCFG_GLOBAL },
+ { "clientaliveinterval", sClientAliveInterval, SSHCFG_ALL },
+ { "clientalivecountmax", sClientAliveCountMax, SSHCFG_ALL },
+ { "authorizedkeysfile", sAuthorizedKeysFile, SSHCFG_ALL },
+ { "authorizedkeysfile2", sAuthorizedKeysFile2, SSHCFG_ALL },
+ { "useprivilegeseparation", sUsePrivilegeSeparation, SSHCFG_GLOBAL},
+ { "acceptenv", sAcceptEnv, SSHCFG_ALL },
+ { "permittunnel", sPermitTunnel, SSHCFG_ALL },
+ { "match", sMatch, SSHCFG_ALL },
+ { NULL, sBadOption, 0 }
};
/*
@@ -386,13 +396,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);
@@ -437,15 +449,49 @@ add_one_listen_addr(ServerOptions *optio
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 0 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
+ */
+
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;
cp = line;
arg = strdelim(&cp);
@@ -456,7 +502,26 @@ process_server_config_line(ServerOptions
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;
+ }
+ debug("match: line %s active %d flags %d", line, *activep, flags);
+ 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) {
/* Portable-specific options */
case sUsePAM:
@@ -494,7 +559,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;
@@ -574,7 +639,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)
@@ -625,7 +690,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;
@@ -961,6 +1026,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);
}
@@ -988,6 +1055,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);
@@ -1044,18 +1122,124 @@ load_server_config(const char *filename,
}
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)
{
- int linenum, bad_options = 0;
+ u_int i;
+ ServerOptions mo;
+
+ initialize_server_options(&mo);
+ parse_server_config(&mo, "reprocess config", &cfg, user, host, address);
+
+ /* now copy any (supported) values set */
+ if (mo.use_pam != -1)
+ options->use_pam = mo.use_pam;
+ if (mo.num_accept_env > 0) {
+ for (i = 0; i < mo.num_accept_env; i++) {
+ if (options->num_accept_env >= MAX_ACCEPT_ENV)
+ fatal("Too many allow env in Match block.");
+ options->accept_env[options->num_accept_env++] =
+ mo.accept_env[i];
+ }
+ }
+ if (mo.allow_tcp_forwarding != -1)
+ options->allow_tcp_forwarding = mo.allow_tcp_forwarding;
+ if (mo.authorized_keys_file != NULL) {
+ if (options->authorized_keys_file != NULL)
+ xfree(options->authorized_keys_file);
+ options->authorized_keys_file = mo.authorized_keys_file;
+ }
+ if (mo.authorized_keys_file2 != NULL) {
+ if (options->authorized_keys_file2 != NULL)
+ xfree(options->authorized_keys_file2);
+ options->authorized_keys_file2 = mo.authorized_keys_file2;
+ }
+ if (mo.banner != NULL) {
+ if (options->banner != NULL)
+ xfree(options->banner);
+ options->banner = mo.banner;
+ }
+ if (mo.password_authentication != -1)
+ options->password_authentication = mo.password_authentication;
+ if (mo.challenge_response_authentication != -1)
+ options->challenge_response_authentication =
+ mo.challenge_response_authentication;
+ if (mo.client_alive_count_max != -1)
+ options->client_alive_count_max = mo.client_alive_count_max;
+ if (mo.client_alive_interval != -1)
+ options->client_alive_interval = mo.client_alive_interval;
+ if (mo.gateway_ports != -1)
+ options->gateway_ports = mo.gateway_ports;
+ if (mo.gss_authentication != -1)
+ options->gss_authentication = mo.gss_authentication;
+ if (mo.hostbased_authentication != -1)
+ options->hostbased_authentication = mo.hostbased_authentication;
+ if (mo.hostbased_uses_name_from_packet_only != -1)
+ options->hostbased_uses_name_from_packet_only =
+ mo.hostbased_uses_name_from_packet_only;
+ if (mo.kerberos_authentication != -1)
+ options->kerberos_authentication = mo.kerberos_authentication;
+ if (mo.kerberos_or_local_passwd != -1)
+ options->kerberos_or_local_passwd = mo.kerberos_or_local_passwd;
+ if (mo.kerberos_ticket_cleanup != -1)
+ options->kerberos_ticket_cleanup = mo.kerberos_ticket_cleanup;
+ if (mo.kerberos_get_afs_token != -1)
+ options->kerberos_get_afs_token = mo.kerberos_get_afs_token;
+ if (mo.login_grace_time != -1)
+ options->login_grace_time = mo.login_grace_time;
+ if (mo.log_facility != -1)
+ options->log_facility = mo.log_facility;
+ if (mo.log_level != -1)
+ options->log_level = mo.log_level;
+ if (mo.permit_root_login != -1)
+ options->permit_root_login = mo.permit_root_login;
+ if (mo.max_authtries != -1)
+ options->max_authtries = mo.max_authtries;
+ if (mo.permit_empty_passwd != -1)
+ options->permit_empty_passwd = mo.permit_empty_passwd;
+ if (mo.permit_tun != -1)
+ options->permit_tun = mo.permit_tun;
+ if (mo.permit_user_env != -1)
+ options->permit_user_env = mo.permit_user_env;
+ if (mo.print_motd != -1)
+ options->print_motd = mo.print_motd;
+ if (mo.pubkey_authentication != -1)
+ options->pubkey_authentication = mo.pubkey_authentication;
+ if (mo.rsa_authentication != -1)
+ options->rsa_authentication = mo.rsa_authentication;
+ if (mo.strict_modes != -1)
+ options->strict_modes = mo.strict_modes;
+ if (mo.use_login != -1)
+ options->use_login = mo.use_login;
+ if (mo.xauth_location != NULL) {
+ if (options->xauth_location != NULL)
+ xfree(options->xauth_location);
+ options->xauth_location = mo.xauth_location;
+ }
+ if (mo.x11_display_offset != -1)
+ options->x11_display_offset = mo.x11_display_offset;
+ if (mo.x11_forwarding != -1)
+ options->x11_forwarding = mo.x11_forwarding;
+ if (mo.x11_use_localhost != -1)
+ options->x11_use_localhost = mo.x11_use_localhost;
+}
+
+void
+parse_server_config(ServerOptions *options, const char *filename, Buffer *conf,
+ const char *user, const char *host, const char *address)
+{
+ 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);
Index: servconf.h
===================================================================
RCS file: /usr/local/src/security/openssh/cvs/openssh_cvs/servconf.h,v
retrieving revision 1.64
diff -u -p -r1.64 servconf.h
--- servconf.h 13 Dec 2005 08:29:03 -0000 1.64
+++ servconf.h 2 Apr 2006 01:36:33 -0000
@@ -141,8 +141,12 @@ 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 *);
#endif /* SERVCONF_H */
Index: sshd.c
===================================================================
RCS file: /usr/local/src/security/openssh/cvs/openssh_cvs/sshd.c,v
retrieving revision 1.320
diff -u -p -r1.320 sshd.c
--- sshd.c 24 Dec 2005 03:59:12 -0000 1.320
+++ sshd.c 2 Apr 2006 01:37:38 -0000
@@ -201,12 +201,15 @@ int *startup_pipes = NULL;
int startup_pipe; /* in child */
/* variables used for privilege separation */
-int use_privsep;
+int use_privsep = -1; /* Needs to be accessable in many places */
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;
#ifdef HAVE_SECUREWARE
(void)set_auth_parameters(ac, av);
@@ -1011,7 +1013,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;
@@ -1070,10 +1072,7 @@ main(int ac, char **av)
load_server_config(config_file_name, &cfg);
parse_server_config(&options,
- rexeced_flag ? "rexec" : config_file_name, &cfg);
-
- if (!rexec_flag)
- buffer_free(&cfg);
+ rexeced_flag ? "rexec" : config_file_name, &cfg, NULL, NULL, NULL);
seed_rng();
More information about the openssh-unix-dev
mailing list