mirror of
https://github.com/openbsd/src.git
synced 2026-06-18 23:33:33 +02:00
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@
This commit is contained in:
@@ -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.
|
||||
*
|
||||
@@ -25,6 +25,7 @@
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
@@ -41,7 +42,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*,"
|
||||
|
||||
+27
-1
@@ -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@citi.umich.edu>
|
||||
* Copyright 2002 Markus Friedl <markus@openbsd.org>
|
||||
@@ -102,6 +102,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 *);
|
||||
@@ -139,6 +140,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;
|
||||
@@ -164,6 +166,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},
|
||||
@@ -246,6 +249,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 */
|
||||
@@ -646,6 +650,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)
|
||||
{
|
||||
@@ -661,6 +679,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 ||
|
||||
@@ -788,6 +810,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");
|
||||
|
||||
|
||||
@@ -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@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,
|
||||
|
||||
@@ -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@citi.umich.edu>
|
||||
* Copyright 2002 Markus Friedl <markus@openbsd.org>
|
||||
@@ -251,6 +251,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,
|
||||
|
||||
@@ -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@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);
|
||||
|
||||
@@ -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@cs.hut.fi>
|
||||
@@ -18,6 +18,7 @@
|
||||
|
||||
#include <sys/queue.h>
|
||||
|
||||
#include <stdint.h>
|
||||
#include <signal.h>
|
||||
#include <termios.h>
|
||||
|
||||
@@ -68,7 +69,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;
|
||||
|
||||
@@ -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:
|
||||
@@ -768,6 +768,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");
|
||||
|
||||
@@ -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:
|
||||
@@ -1132,13 +1132,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 */
|
||||
|
||||
Reference in New Issue
Block a user