From 831e6db69ff8625b6e81c2809aa082abbab6c0b1 Mon Sep 17 00:00:00 2001 From: "djm@openbsd.org" Date: Fri, 19 Dec 2025 00:56:34 +0000 Subject: [PATCH] upstream: don't crash at connection time if the main sshd_config lacks any subsystem directive but one is defined in a Match block bz#3906; ok dtucker OpenBSD-Commit-ID: 2eb9024726d6f10eaa41958faeca9c9ba5ca7d8a --- monitor.c | 4 ++-- monitor_wrap.c | 6 +++--- servconf.c | 7 ++++--- servconf.h | 33 +++++++++++++++++---------------- 4 files changed, 26 insertions(+), 24 deletions(-) diff --git a/monitor.c b/monitor.c index 3867b438b..eac5aa819 100644 --- a/monitor.c +++ b/monitor.c @@ -1,4 +1,4 @@ -/* $OpenBSD: monitor.c,v 1.250 2025/12/16 08:32:50 dtucker Exp $ */ +/* $OpenBSD: monitor.c,v 1.251 2025/12/19 00:56:34 djm Exp $ */ /* * Copyright 2002 Niels Provos * Copyright 2002 Markus Friedl @@ -822,7 +822,7 @@ mm_encode_server_options(struct sshbuf *m) (r = sshbuf_put_cstring(m, options.x)) != 0) \ fatal_fr(r, "assemble %s", #x); \ } while (0) -#define M_CP_STRARRAYOPT(x, nx) do { \ +#define M_CP_STRARRAYOPT(x, nx, clobber) do { \ for (i = 0; i < options.nx; i++) { \ if ((r = sshbuf_put_cstring(m, options.x[i])) != 0) \ fatal_fr(r, "assemble %s", #x); \ diff --git a/monitor_wrap.c b/monitor_wrap.c index e5b620d9c..a5c6308be 100644 --- a/monitor_wrap.c +++ b/monitor_wrap.c @@ -1,4 +1,4 @@ -/* $OpenBSD: monitor_wrap.c,v 1.143 2025/10/09 03:23:33 djm Exp $ */ +/* $OpenBSD: monitor_wrap.c,v 1.144 2025/12/19 00:56:34 djm Exp $ */ /* * Copyright 2002 Niels Provos * Copyright 2002 Markus Friedl @@ -305,7 +305,7 @@ mm_decode_activate_server_options(struct ssh *ssh, struct sshbuf *m) (r = sshbuf_get_cstring(m, &newopts->x, NULL)) != 0) \ fatal_fr(r, "parse %s", #x); \ } while (0) -#define M_CP_STRARRAYOPT(x, nx) do { \ +#define M_CP_STRARRAYOPT(x, nx, clobber) do { \ newopts->x = newopts->nx == 0 ? \ NULL : xcalloc(newopts->nx, sizeof(*newopts->x)); \ for (i = 0; i < newopts->nx; i++) { \ @@ -327,7 +327,7 @@ mm_decode_activate_server_options(struct ssh *ssh, struct sshbuf *m) /* use the macro hell to clean up too */ #define M_CP_STROPT(x) free(newopts->x) -#define M_CP_STRARRAYOPT(x, nx) do { \ +#define M_CP_STRARRAYOPT(x, nx, clobber) do { \ for (i = 0; i < newopts->nx; i++) \ free(newopts->x[i]); \ free(newopts->x); \ diff --git a/servconf.c b/servconf.c index 57a14294c..3452e1a30 100644 --- a/servconf.c +++ b/servconf.c @@ -1,4 +1,4 @@ -/* $OpenBSD: servconf.c,v 1.441 2025/12/19 00:48:04 djm Exp $ */ +/* $OpenBSD: servconf.c,v 1.442 2025/12/19 00:56:34 djm Exp $ */ /* * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland * All rights reserved @@ -2992,7 +2992,7 @@ copy_set_server_options(ServerOptions *dst, ServerOptions *src, int preauth) dst->n = xstrdup(src->n); \ } \ } while(0) -#define M_CP_STRARRAYOPT(s, num_s) do {\ +#define M_CP_STRARRAYOPT(s, num_s, clobber) do {\ u_int i; \ if (src->num_s != 0) { \ for (i = 0; i < dst->num_s; i++) \ @@ -3001,7 +3001,8 @@ copy_set_server_options(ServerOptions *dst, ServerOptions *src, int preauth) dst->s = xcalloc(src->num_s, sizeof(*dst->s)); \ for (i = 0; i < src->num_s; i++) \ dst->s[i] = xstrdup(src->s[i]); \ - dst->num_s = src->num_s; \ + if (clobber) \ + dst->num_s = src->num_s; \ } \ } while(0) diff --git a/servconf.h b/servconf.h index 73d952f09..bf47f838e 100644 --- a/servconf.h +++ b/servconf.h @@ -1,4 +1,4 @@ -/* $OpenBSD: servconf.h,v 1.172 2025/12/16 08:32:50 dtucker Exp $ */ +/* $OpenBSD: servconf.h,v 1.173 2025/12/19 00:56:34 djm Exp $ */ /* * Author: Tatu Ylonen @@ -303,21 +303,22 @@ TAILQ_HEAD(include_list, include_item); M_CP_STROPT(routing_domain); \ M_CP_STROPT(permit_user_env_allowlist); \ M_CP_STROPT(pam_service_name); \ - M_CP_STRARRAYOPT(authorized_keys_files, num_authkeys_files); \ - M_CP_STRARRAYOPT(allow_users, num_allow_users); \ - M_CP_STRARRAYOPT(deny_users, num_deny_users); \ - M_CP_STRARRAYOPT(allow_groups, num_allow_groups); \ - M_CP_STRARRAYOPT(deny_groups, num_deny_groups); \ - M_CP_STRARRAYOPT(accept_env, num_accept_env); \ - M_CP_STRARRAYOPT(setenv, num_setenv); \ - M_CP_STRARRAYOPT(auth_methods, num_auth_methods); \ - M_CP_STRARRAYOPT(permitted_opens, num_permitted_opens); \ - M_CP_STRARRAYOPT(permitted_listens, num_permitted_listens); \ - M_CP_STRARRAYOPT(channel_timeouts, num_channel_timeouts); \ - M_CP_STRARRAYOPT(log_verbose, num_log_verbose); \ - M_CP_STRARRAYOPT(subsystem_name, num_subsystems); \ - M_CP_STRARRAYOPT(subsystem_command, num_subsystems); \ - M_CP_STRARRAYOPT(subsystem_args, num_subsystems); \ + M_CP_STRARRAYOPT(authorized_keys_files, num_authkeys_files, 1);\ + M_CP_STRARRAYOPT(allow_users, num_allow_users, 1); \ + M_CP_STRARRAYOPT(deny_users, num_deny_users, 1); \ + M_CP_STRARRAYOPT(allow_groups, num_allow_groups, 1); \ + M_CP_STRARRAYOPT(deny_groups, num_deny_groups, 1); \ + M_CP_STRARRAYOPT(accept_env, num_accept_env, 1); \ + M_CP_STRARRAYOPT(setenv, num_setenv, 1); \ + M_CP_STRARRAYOPT(auth_methods, num_auth_methods, 1); \ + M_CP_STRARRAYOPT(permitted_opens, num_permitted_opens, 1); \ + M_CP_STRARRAYOPT(permitted_listens, num_permitted_listens, 1); \ + M_CP_STRARRAYOPT(channel_timeouts, num_channel_timeouts, 1); \ + M_CP_STRARRAYOPT(log_verbose, num_log_verbose, 1); \ + /* Note: don't clobber num_subsystems until all copies */ \ + M_CP_STRARRAYOPT(subsystem_name, num_subsystems, 0); \ + M_CP_STRARRAYOPT(subsystem_command, num_subsystems, 0); \ + M_CP_STRARRAYOPT(subsystem_args, num_subsystems, 1); \ } while (0) void initialize_server_options(ServerOptions *); -- 2.43.0