1- /* $OpenBSD: monitor.c,v 1.252 2026/02/08 19:54:31 dtucker Exp $ */
1+ /* $OpenBSD: monitor.c,v 1.253 2026/03/02 02:40:15 djm Exp $ */
22/*
33 * Copyright 2002 Niels Provos <provos@citi.umich.edu>
44 * Copyright 2002 Markus Friedl <markus@openbsd.org>
@@ -106,6 +106,7 @@ static struct sshbuf *child_state;
106106/* Functions on the monitor that answer unprivileged requests */
107107
108108int mm_answer_moduli (struct ssh * , int , struct sshbuf * );
109+ int mm_answer_setcompat (struct ssh * , int , struct sshbuf * );
109110int mm_answer_sign (struct ssh * , int , struct sshbuf * );
110111int mm_answer_pwnamallow (struct ssh * , int , struct sshbuf * );
111112int mm_answer_auth2_read_banner (struct ssh * , int , struct sshbuf * );
@@ -157,6 +158,7 @@ static u_char *session_id2 = NULL;
157158static pid_t monitor_child_pid ;
158159static int auth_attempted = 0 ;
159160static int invalid_user = 0 ;
161+ static int compat_set = 0 ;
160162
161163struct mon_table {
162164 enum monitor_reqtype type ;
@@ -182,6 +184,7 @@ struct mon_table mon_dispatch_proto20[] = {
182184#ifdef WITH_OPENSSL
183185 {MONITOR_REQ_MODULI , MON_ONCE , mm_answer_moduli },
184186#endif
187+ {MONITOR_REQ_SETCOMPAT , MON_ONCE , mm_answer_setcompat },
185188 {MONITOR_REQ_SIGN , MON_ONCE , mm_answer_sign },
186189 {MONITOR_REQ_PWNAM , MON_ONCE , mm_answer_pwnamallow },
187190 {MONITOR_REQ_AUTHSERV , MON_ONCE , mm_answer_authserv },
@@ -283,6 +286,7 @@ monitor_child_preauth(struct ssh *ssh, struct monitor *pmonitor)
283286 /* Permit requests for state, moduli and signatures */
284287 monitor_permit (mon_dispatch , MONITOR_REQ_STATE , 1 );
285288 monitor_permit (mon_dispatch , MONITOR_REQ_MODULI , 1 );
289+ monitor_permit (mon_dispatch , MONITOR_REQ_SETCOMPAT , 1 );
286290 monitor_permit (mon_dispatch , MONITOR_REQ_SIGN , 1 );
287291
288292 /* The first few requests do not require asynchronous access */
@@ -701,6 +705,20 @@ mm_answer_moduli(struct ssh *ssh, int sock, struct sshbuf *m)
701705}
702706#endif
703707
708+ int
709+ mm_answer_setcompat (struct ssh * ssh , int sock , struct sshbuf * m )
710+ {
711+ int r ;
712+
713+ debug3_f ("entering" );
714+
715+ if ((r = sshbuf_get_u32 (m , & ssh -> compat )) != 0 )
716+ fatal_fr (r , "parse" );
717+ compat_set = 1 ;
718+
719+ return (0 );
720+ }
721+
704722int
705723mm_answer_sign (struct ssh * ssh , int sock , struct sshbuf * m )
706724{
@@ -716,6 +734,10 @@ mm_answer_sign(struct ssh *ssh, int sock, struct sshbuf *m)
716734
717735 debug3_f ("entering" );
718736
737+ /* Make sure the unpriv process sent the compat bits already */
738+ if (!compat_set )
739+ fatal_f ("state error: setcompat never called" );
740+
719741 if ((r = sshkey_froms (m , & pubkey )) != 0 ||
720742 (r = sshbuf_get_string (m , & p , & datlen )) != 0 ||
721743 (r = sshbuf_get_cstring (m , & alg , NULL )) != 0 ||
@@ -843,6 +865,10 @@ mm_answer_pwnamallow(struct ssh *ssh, int sock, struct sshbuf *m)
843865
844866 debug3_f ("entering" );
845867
868+ /* Make sure the unpriv process sent the compat bits already */
869+ if (!compat_set )
870+ fatal_f ("state error: setcompat never called" );
871+
846872 if (authctxt -> attempt ++ != 0 )
847873 fatal_f ("multiple attempts for getpwnam" );
848874
0 commit comments