[openssh-commits] [openssh] branch master updated: upstream: Move banner exchange to sshd-auth process

git+noreply at mindrot.org git+noreply at mindrot.org
Mon Mar 2 13:43:33 AEDT 2026


This is an automated email from the git hooks/post-receive script.

djm pushed a commit to branch master
in repository openssh.

The following commit(s) were added to refs/heads/master by this push:
     new bb781f02d upstream: Move banner exchange to sshd-auth process
bb781f02d is described below

commit bb781f02d4efd178e329a62a838962bee16e3e9b
Author: djm at openbsd.org <djm at openbsd.org>
AuthorDate: Mon Mar 2 02:40:15 2026 +0000

    upstream: Move banner exchange to sshd-auth process
    
    Previously, exchange of the initial SSH- banners was performed
    by the privileged sshd-session monitor. This moves it to the
    unprivileged sshd-auth subprocess, removing ~200 LoC from the
    monitor's privileged attack surface.
    
    The monitor gains a new "setcompat" RPC to allow sshd-auth to
    inform it of bug compat flags picked up from the client's banner.
    
    feedback dtucker@, ok markus@ deraadt@
    
    OpenBSD-Commit-ID: d767eb1183630d754d521d9f0d84a6c72fbe7fc8
---
 compat.c       |  5 +++--
 monitor.c      | 28 +++++++++++++++++++++++++++-
 monitor.h      |  3 ++-
 monitor_wrap.c | 17 ++++++++++++++++-
 monitor_wrap.h |  3 ++-
 packet.h       |  5 +++--
 sshd-auth.c    | 10 +++++++++-
 sshd-session.c |  9 +--------
 8 files changed, 63 insertions(+), 17 deletions(-)

diff --git a/compat.c b/compat.c
index 31607e3ff..4cc7ca61a 100644
--- a/compat.c
+++ b/compat.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: compat.c,v 1.127 2026/02/14 00:18:34 jsg Exp $ */
+/* $OpenBSD: compat.c,v 1.128 2026/03/02 02:40:15 djm Exp $ */
 /*
  * Copyright (c) 1999, 2000, 2001, 2002 Markus Friedl.  All rights reserved.
  *
@@ -27,6 +27,7 @@
 
 #include <sys/types.h>
 
+#include <stdint.h>
 #include <stdlib.h>
 #include <stdarg.h>
 
@@ -43,7 +44,7 @@ compat_banner(struct ssh *ssh, const char *version)
 	int i;
 	static struct {
 		char	*pat;
-		int	bugs;
+		uint32_t bugs;
 	} check[] = {
 		{ "OpenSSH_2.*,"
 		  "OpenSSH_3.0*,"
diff --git a/monitor.c b/monitor.c
index 290b7f536..7a71a6586 100644
--- a/monitor.c
+++ b/monitor.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: monitor.c,v 1.252 2026/02/08 19:54:31 dtucker Exp $ */
+/* $OpenBSD: monitor.c,v 1.253 2026/03/02 02:40:15 djm Exp $ */
 /*
  * Copyright 2002 Niels Provos <provos at citi.umich.edu>
  * Copyright 2002 Markus Friedl <markus at openbsd.org>
@@ -106,6 +106,7 @@ static struct sshbuf *child_state;
 /* Functions on the monitor that answer unprivileged requests */
 
 int mm_answer_moduli(struct ssh *, int, struct sshbuf *);
+int mm_answer_setcompat(struct ssh *, int, struct sshbuf *);
 int mm_answer_sign(struct ssh *, int, struct sshbuf *);
 int mm_answer_pwnamallow(struct ssh *, int, struct sshbuf *);
 int mm_answer_auth2_read_banner(struct ssh *, int, struct sshbuf *);
@@ -157,6 +158,7 @@ static u_char *session_id2 = NULL;
 static pid_t monitor_child_pid;
 static int auth_attempted = 0;
 static int invalid_user = 0;
+static int compat_set = 0;
 
 struct mon_table {
 	enum monitor_reqtype type;
@@ -182,6 +184,7 @@ struct mon_table mon_dispatch_proto20[] = {
 #ifdef WITH_OPENSSL
     {MONITOR_REQ_MODULI, MON_ONCE, mm_answer_moduli},
 #endif
+    {MONITOR_REQ_SETCOMPAT, MON_ONCE, mm_answer_setcompat},
     {MONITOR_REQ_SIGN, MON_ONCE, mm_answer_sign},
     {MONITOR_REQ_PWNAM, MON_ONCE, mm_answer_pwnamallow},
     {MONITOR_REQ_AUTHSERV, MON_ONCE, mm_answer_authserv},
@@ -283,6 +286,7 @@ monitor_child_preauth(struct ssh *ssh, struct monitor *pmonitor)
 	/* Permit requests for state, moduli and signatures */
 	monitor_permit(mon_dispatch, MONITOR_REQ_STATE, 1);
 	monitor_permit(mon_dispatch, MONITOR_REQ_MODULI, 1);
+	monitor_permit(mon_dispatch, MONITOR_REQ_SETCOMPAT, 1);
 	monitor_permit(mon_dispatch, MONITOR_REQ_SIGN, 1);
 
 	/* The first few requests do not require asynchronous access */
@@ -701,6 +705,20 @@ mm_answer_moduli(struct ssh *ssh, int sock, struct sshbuf *m)
 }
 #endif
 
+int
+mm_answer_setcompat(struct ssh *ssh, int sock, struct sshbuf *m)
+{
+	int r;
+
+	debug3_f("entering");
+
+	if ((r = sshbuf_get_u32(m, &ssh->compat)) != 0)
+		fatal_fr(r, "parse");
+	compat_set = 1;
+
+	return (0);
+}
+
 int
 mm_answer_sign(struct ssh *ssh, int sock, struct sshbuf *m)
 {
@@ -716,6 +734,10 @@ mm_answer_sign(struct ssh *ssh, int sock, struct sshbuf *m)
 
 	debug3_f("entering");
 
+	/* Make sure the unpriv process sent the compat bits already */
+	if (!compat_set)
+		fatal_f("state error: setcompat never called");
+
 	if ((r = sshkey_froms(m, &pubkey)) != 0 ||
 	    (r = sshbuf_get_string(m, &p, &datlen)) != 0 ||
 	    (r = sshbuf_get_cstring(m, &alg, NULL)) != 0 ||
@@ -843,6 +865,10 @@ mm_answer_pwnamallow(struct ssh *ssh, int sock, struct sshbuf *m)
 
 	debug3_f("entering");
 
+	/* Make sure the unpriv process sent the compat bits already */
+	if (!compat_set)
+		fatal_f("state error: setcompat never called");
+
 	if (authctxt->attempt++ != 0)
 		fatal_f("multiple attempts for getpwnam");
 
diff --git a/monitor.h b/monitor.h
index a6211af99..fe0b00b2e 100644
--- a/monitor.h
+++ b/monitor.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: monitor.h,v 1.27 2026/02/09 21:23:35 dtucker Exp $ */
+/* $OpenBSD: monitor.h,v 1.28 2026/03/02 02:40:15 djm Exp $ */
 
 /*
  * Copyright 2002 Niels Provos <provos at citi.umich.edu>
@@ -39,6 +39,7 @@ enum monitor_reqtype {
 	MONITOR_REQ_AUTHPASSWORD = 12, MONITOR_ANS_AUTHPASSWORD = 13,
 	MONITOR_REQ_BSDAUTHQUERY = 14, MONITOR_ANS_BSDAUTHQUERY = 15,
 	MONITOR_REQ_BSDAUTHRESPOND = 16, MONITOR_ANS_BSDAUTHRESPOND = 17,
+	MONITOR_REQ_SETCOMPAT = 18,
 	MONITOR_REQ_KEYALLOWED = 22, MONITOR_ANS_KEYALLOWED = 23,
 	MONITOR_REQ_KEYVERIFY = 24, MONITOR_ANS_KEYVERIFY = 25,
 	MONITOR_REQ_KEYEXPORT = 26,
diff --git a/monitor_wrap.c b/monitor_wrap.c
index 383bae4b0..81596a4cc 100644
--- a/monitor_wrap.c
+++ b/monitor_wrap.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: monitor_wrap.c,v 1.145 2026/02/08 19:54:31 dtucker Exp $ */
+/* $OpenBSD: monitor_wrap.c,v 1.146 2026/03/02 02:40:15 djm Exp $ */
 /*
  * Copyright 2002 Niels Provos <provos at citi.umich.edu>
  * Copyright 2002 Markus Friedl <markus at openbsd.org>
@@ -254,6 +254,21 @@ mm_choose_dh(int min, int nbits, int max)
 }
 #endif
 
+void
+mm_sshkey_setcompat(struct ssh *ssh)
+{
+	struct sshbuf *m;
+	int r;
+
+	debug3_f("entering");
+	if ((m = sshbuf_new()) == NULL)
+		fatal_f("sshbuf_new failed");
+	if ((r = sshbuf_put_u32(m, ssh->compat)) != 0)
+		fatal_fr(r, "assemble");
+
+	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_SETCOMPAT, m);
+}
+
 int
 mm_sshkey_sign(struct ssh *ssh, struct sshkey *key, u_char **sigp, size_t *lenp,
     const u_char *data, size_t datalen, const char *hostkey_alg,
diff --git a/monitor_wrap.h b/monitor_wrap.h
index c87295388..c2f7f97d9 100644
--- a/monitor_wrap.h
+++ b/monitor_wrap.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: monitor_wrap.h,v 1.53 2025/07/04 07:47:35 djm Exp $ */
+/* $OpenBSD: monitor_wrap.h,v 1.54 2026/03/02 02:40:15 djm Exp $ */
 
 /*
  * Copyright 2002 Niels Provos <provos at citi.umich.edu>
@@ -46,6 +46,7 @@ int mm_is_monitor(void);
 #ifdef WITH_OPENSSL
 DH *mm_choose_dh(int, int, int);
 #endif
+void mm_sshkey_setcompat(struct ssh *);
 int mm_sshkey_sign(struct ssh *, struct sshkey *, u_char **, size_t *,
     const u_char *, size_t, const char *, const char *,
     const char *, u_int compat);
diff --git a/packet.h b/packet.h
index 6d6a064bd..10d42202c 100644
--- a/packet.h
+++ b/packet.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: packet.h,v 1.105 2026/02/08 17:50:49 dtucker Exp $ */
+/* $OpenBSD: packet.h,v 1.106 2026/03/02 02:40:15 djm Exp $ */
 
 /*
  * Author: Tatu Ylonen <ylo at cs.hut.fi>
@@ -18,6 +18,7 @@
 
 #include <sys/queue.h>
 
+#include <stdint.h>
 #include <signal.h>
 #include <termios.h>
 
@@ -74,7 +75,7 @@ struct ssh {
 	int dispatch_skip_packets;
 
 	/* datafellows */
-	int compat;
+	uint32_t compat;
 
 	/* Lists for private and public keys */
 	TAILQ_HEAD(, key_entry) private_keys;
diff --git a/sshd-auth.c b/sshd-auth.c
index 8f9066122..a871b29a8 100644
--- a/sshd-auth.c
+++ b/sshd-auth.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: sshd-auth.c,v 1.12 2026/02/11 17:05:32 dtucker Exp $ */
+/* $OpenBSD: sshd-auth.c,v 1.13 2026/03/02 02:40:15 djm Exp $ */
 /*
  * SSH2 implementation:
  * Privilege Separation:
@@ -811,6 +811,14 @@ do_ssh2_kex(struct ssh *ssh)
 
 	free(hkalgs);
 
+	if ((r = kex_exchange_identification(ssh, -1,
+	    options.version_addendum)) != 0)
+		sshpkt_fatal(ssh, r, "banner exchange");
+	mm_sshkey_setcompat(ssh); /* tell monitor */
+
+	if ((ssh->compat & SSH_BUG_NOREKEY))
+		debug("client does not support rekeying");
+
 	/* start key exchange */
 	if ((r = kex_setup(ssh, myproposal)) != 0)
 		fatal_r(r, "kex_setup");
diff --git a/sshd-session.c b/sshd-session.c
index 29de97fa6..79b867617 100644
--- a/sshd-session.c
+++ b/sshd-session.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: sshd-session.c,v 1.20 2026/02/09 21:38:14 dtucker Exp $ */
+/* $OpenBSD: sshd-session.c,v 1.21 2026/03/02 02:40:15 djm Exp $ */
 /*
  * SSH2 implementation:
  * Privilege Separation:
@@ -1220,13 +1220,6 @@ main(int ac, char **av)
 			fatal("login grace time setitimer failed");
 	}
 
-	if ((r = kex_exchange_identification(ssh, -1,
-	    options.version_addendum)) != 0)
-		sshpkt_fatal(ssh, r, "banner exchange");
-
-	if ((ssh->compat & SSH_BUG_NOREKEY))
-		debug("client does not support rekeying");
-
 	ssh_packet_set_nonblocking(ssh);
 
 	/* allocate authentication context */

-- 
To stop receiving notification emails like this one, please contact
djm at mindrot.org.


More information about the openssh-commits mailing list