sshd config parser

Darren Tucker dtucker at zip.com.au
Sun Apr 2 00:10:24 EST 2006


On Sat, Apr 01, 2006 at 09:19:19PM +1000, Darren Tucker wrote:
> On Thu, Mar 30, 2006 at 12:18:04AM +1100, Darren Tucker wrote:
> Here's some initial work toward this.  At the moment it only supports
> a couple of existing directives (AllowTcpForwarding, GatewayPorts and
> AcceptEnv).  Example syntax is below (from my test config).

Here's some more work toward this.

It now supports multiple criteria per "Match" line (in theory it did
before but it didn't, well, work :-)

The tokens that it supports inside a match block are the directives
corresponding to these:
use_pam
num_accept_env
allow_tcp_forwarding
banner
password_authentication
challenge_response_authentication
client_alive_count_max
client_alive_interval
gateway_ports
gss_authentication
hostbased_authentication
kerberos_authentication
kerberos_or_local_passwd
kerberos_ticket_cleanup
kerberos_get_afs_token
login_grace_time
log_level
max_authtries
permit_tun
pubkey_authentication
rsa_authentication
strict_modes
use_login
x11_forwarding
x11_use_localhost

> Diff is against 4.3p2.  There are surely bugs (consider it a working
> prototype).  Feedback welcome.

Same still applies.

-- 
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	1 Apr 2006 11:36:30 -0000
@@ -587,3 +587,51 @@ fakepw(void)
 
 	return (&fake);
 }
+
+int
+cfg_match_line(Authctxt *ctxt, char **condition)
+{
+	int result = 1;
+	char *arg, *attrib, *cp = *condition;
+	const char *remhost;
+	size_t len;
+
+	if (ctxt == NULL)
+		debug("checking syntax for 'Match %s'", cp);
+	else
+		debug("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 (!ctxt)
+				continue;
+			if (match_pattern_list(ctxt->user, arg, len, 0) != 1)
+				/* XXX what about negative match? */
+				result = 0;
+		} else if (strcasecmp(attrib, "host") == 0) {
+			if (!ctxt)
+				continue;
+			remhost = get_canonical_hostname(options.use_dns);
+			debug("match remhost %s arg %s", remhost, arg);
+			if (match_hostname(remhost, arg, len) != 1)
+				result = 0;
+		} else if (strcasecmp(attrib, "address") == 0) {
+			if (!ctxt)
+				continue;
+			remhost = get_remote_ipaddr();
+			if (match_hostname(remhost, arg, len) != 1)
+				result = 0;
+		} else {
+			error("Unsupported Match attribute %s", attrib);
+			return -1;
+		}
+	}
+	*condition = cp;
+	debug("cfg_check_match: returning %d", result);
+	return result;
+}
Index: auth.h
===================================================================
RCS file: /usr/local/src/security/openssh/cvs/openssh_cvs/auth.h,v
retrieving revision 1.68
diff -u -p -r1.68 auth.h
--- auth.h	7 Jul 2005 01:50:20 -0000	1.68
+++ auth.h	1 Apr 2006 10:41:07 -0000
@@ -185,6 +185,7 @@ void	 auth_debug_send(void);
 void	 auth_debug_reset(void);
 
 struct passwd *fakepw(void);
+int	 cfg_match_line(Authctxt *, char **);
 
 int	 sys_auth_passwd(Authctxt *, const char *);
 
Index: auth1.c
===================================================================
RCS file: /usr/local/src/security/openssh/cvs/openssh_cvs/auth1.c,v
retrieving revision 1.111
diff -u -p -r1.111 auth1.c
--- auth1.c	17 Jul 2005 07:26:44 -0000	1.111
+++ auth1.c	1 Apr 2006 08:40:47 -0000
@@ -385,6 +385,8 @@ do_authentication(Authctxt *authctxt)
 	authctxt->user = user;
 	authctxt->style = style;
 
+	parse_server_match_config(&options, authctxt);
+
 	/* Verify that the user is a valid user. */
 	if ((authctxt->pw = PRIVSEP(getpwnamallow(user))) != NULL)
 		authctxt->valid = 1;
Index: auth2.c
===================================================================
RCS file: /usr/local/src/security/openssh/cvs/openssh_cvs/auth2.c,v
retrieving revision 1.136
diff -u -p -r1.136 auth2.c
--- auth2.c	24 Sep 2005 02:43:51 -0000	1.136
+++ auth2.c	1 Apr 2006 08:41:11 -0000
@@ -153,6 +153,7 @@ input_userauth_request(int type, u_int32
 		/* setup auth context */
 		authctxt->pw = PRIVSEP(getpwnamallow(user));
 		authctxt->user = xstrdup(user);
+		parse_server_match_config(&options, authctxt);
 		if (authctxt->pw && strcmp(service, "ssh-connection")==0) {
 			authctxt->valid = 1;
 			debug2("input_userauth_request: setting up authctxt for %s", user);
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	1 Apr 2006 08:42:01 -0000
@@ -592,6 +592,8 @@ mm_answer_pwnamallow(int sock, Buffer *m
 
 	buffer_clear(m);
 
+	parse_server_match_config(&options, authctxt);
+
 	if (pwent == NULL) {
 		buffer_put_char(m, 0);
 		authctxt->pw = fakepw();
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	1 Apr 2006 12:59:39 -0000
@@ -22,12 +22,15 @@ RCSID("$OpenBSD: servconf.c,v 1.146 2005
 #include "cipher.h"
 #include "kex.h"
 #include "mac.h"
+#include "auth.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 +105,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 +274,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_GLOBAL },
+	{ "syslogfacility", sLogFacility, SSHCFG_GLOBAL },
+	{ "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_GLOBAL },
+	{ "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_ALL },
+	{ "keepalive", sTCPKeepAlive, SSHCFG_ALL },	/* 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_GLOBAL },
+	{ "authorizedkeysfile2", sAuthorizedKeysFile2, SSHCFG_GLOBAL },
+	{ "useprivilegeseparation", sUsePrivilegeSeparation, SSHCFG_GLOBAL},
+	{ "acceptenv", sAcceptEnv, SSHCFG_ALL },
+	{ "permittunnel", sPermitTunnel, SSHCFG_ALL },
+	{ "match", sMatch, SSHCFG_ALL },
+	{ NULL, sBadOption, 0 }
 };
 
 /*
@@ -386,13 +397,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 +450,31 @@ 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.
+ */
+
 int
 process_server_config_line(ServerOptions *options, char *line,
-    const char *filename, int linenum)
+    const char *filename, int linenum, int *activep, Authctxt *ctxt)
 {
 	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 +485,25 @@ 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;
+	}
+	if (*activep == 0 && !(flags & SSHCFG_MATCH)) {
+		if (ctxt == 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 +541,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 +621,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 +672,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 +1008,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 +1037,17 @@ parse_flag:
 			*intptr = value;
 		break;
 
+	case sMatch:
+		if (cmdline)
+			fatal("Match directive not supported as a command-line "
+			   "option");
+		value = cfg_match_line(ctxt, &cp);
+		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 +1104,93 @@ load_server_config(const char *filename,
 }
 
 void
-parse_server_config(ServerOptions *options, const char *filename, Buffer *conf)
+parse_server_match_config(ServerOptions *options, Authctxt *ctxt)
 {
-	int linenum, bad_options = 0;
+	u_int i;
+	ServerOptions mo;
+
+	initialize_server_options(&mo);
+	parse_server_config(&mo, "reprocess config", &cfg, ctxt);
+
+	/* 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.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.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_level != -1)
+		options->log_level = mo.log_level;
+	if (mo.max_authtries != -1)
+		options->max_authtries = mo.max_authtries;
+	if (mo.permit_tun != -1)
+		options->permit_tun = mo.permit_tun;
+	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.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,
+    Authctxt *ctxt)
+{
+	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 = ctxt ? 0 : 1;
 	linenum = 1;
 	while ((cp = strsep(&cbuf, "\n")) != NULL) {
 		if (process_server_config_line(options, cp, filename,
-		    linenum++) != 0)
+		    linenum++, &active, ctxt) != 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	1 Apr 2006 09:23:25 -0000
@@ -17,6 +17,7 @@
 #define SERVCONF_H
 
 #include "buffer.h"
+#include "auth.h"
 
 #define MAX_PORTS		256	/* Max # ports. */
 
@@ -141,8 +142,11 @@ 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 *, Authctxt *);
 void	 load_server_config(const char *, Buffer *);
-void	 parse_server_config(ServerOptions *, const char *, Buffer *);
+void	 parse_server_config(ServerOptions *, const char *, Buffer *,
+	     Authctxt *);
+void	 parse_server_match_config(ServerOptions *, Authctxt *);
 
 #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	1 Apr 2006 09:45:57 -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) != 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);
 
 	seed_rng();
 


More information about the openssh-unix-dev mailing list