- dtucker@cvs.openbsd.org 2007/02/19 10:45:58
     [monitor_wrap.c servconf.c servconf.h monitor.c sshd_config.5]
     Teach Match how handle config directives that are used before
     authentication.  This allows configurations such as permitting password
     authentication from the local net only while requiring pubkey from
     offsite.  ok djm@, man page bits ok jmc@
diff --git a/ChangeLog b/ChangeLog
index c2a22bd..ec16391 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -35,6 +35,12 @@
    - stevesk@cvs.openbsd.org 2007/02/14 14:32:00
      [bufbn.c]
      typos in comments; ok jmc@
+   - dtucker@cvs.openbsd.org 2007/02/19 10:45:58
+     [monitor_wrap.c servconf.c servconf.h monitor.c sshd_config.5]
+     Teach Match how handle config directives that are used before
+     authentication.  This allows configurations such as permitting password
+     authentication from the local net only while requiring pubkey from
+     offsite.  ok djm@, man page bits ok jmc@
 
 20070128
  - (djm) [channels.c serverloop.c] Fix so-called "hang on exit" (bz #52)
@@ -2730,4 +2736,4 @@
    OpenServer 6 and add osr5bigcrypt support so when someone migrates
    passwords between UnixWare and OpenServer they will still work. OK dtucker@
 
-$Id: ChangeLog,v 1.4616 2007/02/19 11:17:28 dtucker Exp $
+$Id: ChangeLog,v 1.4617 2007/02/19 11:25:37 dtucker Exp $
diff --git a/monitor.c b/monitor.c
index 48ae46c..02f2dc8 100644
--- a/monitor.c
+++ b/monitor.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: monitor.c,v 1.89 2006/11/07 10:31:31 markus Exp $ */
+/* $OpenBSD: monitor.c,v 1.90 2007/02/19 10:45:58 dtucker Exp $ */
 /*
  * Copyright 2002 Niels Provos <provos@citi.umich.edu>
  * Copyright 2002 Markus Friedl <markus@openbsd.org>
@@ -642,6 +642,9 @@
 #endif
 	buffer_put_cstring(m, pwent->pw_dir);
 	buffer_put_cstring(m, pwent->pw_shell);
+	buffer_put_string(m, &options, sizeof(options));
+	if (options.banner != NULL)
+		buffer_put_cstring(m, options.banner);
 
  out:
 	debug3("%s: sending MONITOR_ANS_PWNAM: %d", __func__, allowed);
diff --git a/monitor_wrap.c b/monitor_wrap.c
index 3865539..27cc1c5 100644
--- a/monitor_wrap.c
+++ b/monitor_wrap.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: monitor_wrap.c,v 1.54 2006/08/12 20:46:46 miod Exp $ */
+/* $OpenBSD: monitor_wrap.c,v 1.55 2007/02/19 10:45:58 dtucker Exp $ */
 /*
  * Copyright 2002 Niels Provos <provos@citi.umich.edu>
  * Copyright 2002 Markus Friedl <markus@openbsd.org>
@@ -73,6 +73,7 @@
 
 #include "channels.h"
 #include "session.h"
+#include "servconf.h"
 
 /* Imports */
 extern int compat20;
@@ -207,7 +208,8 @@
 {
 	Buffer m;
 	struct passwd *pw;
-	u_int pwlen;
+	u_int len;
+	ServerOptions *newopts;
 
 	debug3("%s entering", __func__);
 
@@ -223,8 +225,8 @@
 		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);
@@ -234,6 +236,16 @@
 #endif
 	pw->pw_dir = buffer_get_string(&m, NULL);
 	pw->pw_shell = buffer_get_string(&m, NULL);
+
+	/* copy options block as a Match directive may have changed some */
+	newopts = buffer_get_string(&m, &len);
+	if (len != sizeof(*newopts))
+		fatal("%s: option block size mismatch", __func__);
+	if (newopts->banner != NULL)
+		newopts->banner = buffer_get_string(&m, NULL);
+	copy_set_server_options(&options, newopts, 1);
+	xfree(newopts);
+
 	buffer_free(&m);
 
 	return (pw);
diff --git a/servconf.c b/servconf.c
index 872ff4a..86949c3 100644
--- a/servconf.c
+++ b/servconf.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: servconf.c,v 1.167 2006/12/14 10:01:14 dtucker Exp $ */
+/* $OpenBSD: servconf.c,v 1.168 2007/02/19 10:45:58 dtucker Exp $ */
 /*
  * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
  *                    All rights reserved
@@ -325,14 +325,14 @@
 	{ "syslogfacility", sLogFacility, SSHCFG_GLOBAL },
 	{ "loglevel", sLogLevel, SSHCFG_GLOBAL },
 	{ "rhostsauthentication", sDeprecated, SSHCFG_GLOBAL },
-	{ "rhostsrsaauthentication", sRhostsRSAAuthentication, SSHCFG_GLOBAL },
-	{ "hostbasedauthentication", sHostbasedAuthentication, SSHCFG_GLOBAL },
+	{ "rhostsrsaauthentication", sRhostsRSAAuthentication, SSHCFG_ALL },
+	{ "hostbasedauthentication", sHostbasedAuthentication, SSHCFG_ALL },
 	{ "hostbasedusesnamefrompacketonly", sHostbasedUsesNameFromPacketOnly, SSHCFG_GLOBAL },
-	{ "rsaauthentication", sRSAAuthentication, SSHCFG_GLOBAL },
-	{ "pubkeyauthentication", sPubkeyAuthentication, SSHCFG_GLOBAL },
+	{ "rsaauthentication", sRSAAuthentication, SSHCFG_ALL },
+	{ "pubkeyauthentication", sPubkeyAuthentication, SSHCFG_ALL },
 	{ "dsaauthentication", sPubkeyAuthentication, SSHCFG_GLOBAL },	/* alias */
 #ifdef KRB5
-	{ "kerberosauthentication", sKerberosAuthentication, SSHCFG_GLOBAL },
+	{ "kerberosauthentication", sKerberosAuthentication, SSHCFG_ALL },
 	{ "kerberosorlocalpasswd", sKerberosOrLocalPasswd, SSHCFG_GLOBAL },
 	{ "kerberosticketcleanup", sKerberosTicketCleanup, SSHCFG_GLOBAL },
 #ifdef USE_AFS
@@ -341,7 +341,7 @@
 	{ "kerberosgetafstoken", sUnsupported, SSHCFG_GLOBAL },
 #endif
 #else
-	{ "kerberosauthentication", sUnsupported, SSHCFG_GLOBAL },
+	{ "kerberosauthentication", sUnsupported, SSHCFG_ALL },
 	{ "kerberosorlocalpasswd", sUnsupported, SSHCFG_GLOBAL },
 	{ "kerberosticketcleanup", sUnsupported, SSHCFG_GLOBAL },
 	{ "kerberosgetafstoken", sUnsupported, SSHCFG_GLOBAL },
@@ -349,15 +349,15 @@
 	{ "kerberostgtpassing", sUnsupported, SSHCFG_GLOBAL },
 	{ "afstokenpassing", sUnsupported, SSHCFG_GLOBAL },
 #ifdef GSSAPI
-	{ "gssapiauthentication", sGssAuthentication, SSHCFG_GLOBAL },
+	{ "gssapiauthentication", sGssAuthentication, SSHCFG_ALL },
 	{ "gssapicleanupcredentials", sGssCleanupCreds, SSHCFG_GLOBAL },
 #else
-	{ "gssapiauthentication", sUnsupported, SSHCFG_GLOBAL },
+	{ "gssapiauthentication", sUnsupported, SSHCFG_ALL },
 	{ "gssapicleanupcredentials", sUnsupported, SSHCFG_GLOBAL },
 #endif
-	{ "passwordauthentication", sPasswordAuthentication, SSHCFG_GLOBAL },
-	{ "kbdinteractiveauthentication", sKbdInteractiveAuthentication, SSHCFG_GLOBAL },
-	{ "challengeresponseauthentication", sChallengeResponseAuthentication, SSHCFG_GLOBAL },
+	{ "passwordauthentication", sPasswordAuthentication, SSHCFG_ALL },
+	{ "kbdinteractiveauthentication", sKbdInteractiveAuthentication, SSHCFG_ALL },
+	{ "challengeresponseauthentication", sChallengeResponseAuthentication, SSHCFG_ALL },
 	{ "skeyauthentication", sChallengeResponseAuthentication, SSHCFG_GLOBAL }, /* alias */
 	{ "checkmail", sDeprecated, SSHCFG_GLOBAL },
 	{ "listenaddress", sListenAddress, SSHCFG_GLOBAL },
@@ -389,7 +389,7 @@
 	{ "subsystem", sSubsystem, SSHCFG_GLOBAL },
 	{ "maxstartups", sMaxStartups, SSHCFG_GLOBAL },
 	{ "maxauthtries", sMaxAuthTries, SSHCFG_GLOBAL },
-	{ "banner", sBanner, SSHCFG_GLOBAL },
+	{ "banner", sBanner, SSHCFG_ALL },
 	{ "usedns", sUseDNS, SSHCFG_GLOBAL },
 	{ "verifyreversemapping", sDeprecated, SSHCFG_GLOBAL },
 	{ "reversemappingcheck", sDeprecated, SSHCFG_GLOBAL },
@@ -1317,30 +1317,56 @@
 
 	initialize_server_options(&mo);
 	parse_server_config(&mo, "reprocess config", &cfg, user, host, address);
-	copy_set_server_options(options, &mo);
+	copy_set_server_options(options, &mo, 0);
 }
 
-/* Copy any (supported) values that are set */
+/* Helper macros */
+#define M_CP_INTOPT(n) do {\
+	if (src->n != -1) \
+		dst->n = src->n; \
+} while (0)
+#define M_CP_STROPT(n) do {\
+	if (src->n != NULL) { \
+		if (dst->n != NULL) \
+			xfree(dst->n); \
+		dst->n = src->n; \
+	} \
+} while(0)
+
+/*
+ * Copy any supported values that are set.
+ *
+ * If the preauth flag is set, we do not bother copying the the string or
+ * array values that are not used pre-authentication, because any that we
+ * do use must be explictly sent in mm_getpwnamallow().
+ */
 void
-copy_set_server_options(ServerOptions *dst, ServerOptions *src)
+copy_set_server_options(ServerOptions *dst, ServerOptions *src, int preauth)
 {
-	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;
-	if (src->adm_forced_command != NULL) {
-		if (dst->adm_forced_command != NULL)
-			xfree(dst->adm_forced_command);
-		dst->adm_forced_command = src->adm_forced_command;
-	}
-	if (src->x11_display_offset != -1)
-		dst->x11_display_offset = src->x11_display_offset;
-	if (src->x11_forwarding != -1)
-		dst->x11_forwarding = src->x11_forwarding;
-	if (src->x11_use_localhost != -1)
-		dst->x11_use_localhost = src->x11_use_localhost;
+	M_CP_INTOPT(password_authentication);
+	M_CP_INTOPT(gss_authentication);
+	M_CP_INTOPT(rsa_authentication);
+	M_CP_INTOPT(pubkey_authentication);
+	M_CP_INTOPT(kerberos_authentication);
+	M_CP_INTOPT(hostbased_authentication);
+	M_CP_INTOPT(kbd_interactive_authentication);
+	M_CP_INTOPT(challenge_response_authentication);
+
+	M_CP_INTOPT(allow_tcp_forwarding);
+	M_CP_INTOPT(gateway_ports);
+	M_CP_INTOPT(x11_display_offset);
+	M_CP_INTOPT(x11_forwarding);
+	M_CP_INTOPT(x11_use_localhost);
+
+	M_CP_STROPT(banner);
+	if (preauth)
+		return;
+	M_CP_STROPT(adm_forced_command);
 }
 
+#undef M_CP_INTOPT
+#undef M_CP_STROPT
+
 void
 parse_server_config(ServerOptions *options, const char *filename, Buffer *conf,
     const char *user, const char *host, const char *address)
diff --git a/servconf.h b/servconf.h
index ad496f6..8a5b950 100644
--- a/servconf.h
+++ b/servconf.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: servconf.h,v 1.79 2006/08/14 12:40:25 dtucker Exp $ */
+/* $OpenBSD: servconf.h,v 1.80 2007/02/19 10:45:58 dtucker Exp $ */
 
 /*
  * Author: Tatu Ylonen <ylo@cs.hut.fi>
@@ -152,6 +152,6 @@
 	     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 *);
+void	 copy_set_server_options(ServerOptions *, ServerOptions *, int);
 
 #endif				/* SERVCONF_H */
diff --git a/sshd_config.5 b/sshd_config.5
index 53207fd..54231d5 100644
--- a/sshd_config.5
+++ b/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.71 2007/01/02 09:57:25 jmc Exp $
+.\" $OpenBSD: sshd_config.5,v 1.72 2007/02/19 10:45:58 dtucker Exp $
 .Dd September 25, 1999
 .Dt SSHD_CONFIG 5
 .Os
@@ -512,9 +512,17 @@
 keyword.
 Available keywords are
 .Cm AllowTcpForwarding ,
+.Cm Banner ,
+.Cm ChallengeResponseAuthentication ,
 .Cm ForceCommand ,
 .Cm GatewayPorts ,
+.Cm GSSApiAuthentication ,
+.Cm KerberosAuthentication ,
+.Cm KeyboardInteractiveAuthentication ,
+.Cm PasswordAuthentication ,
 .Cm PermitOpen ,
+.Cm RhostsRSAAuthentication ,
+.Cm RSAAuthentication ,
 .Cm X11DisplayOffset ,
 .Cm X11Forwarding ,
 and