Make SetEnv directives first-match-wins in both sshd_config and
authordjm <djm@openbsd.org>
Fri, 3 Jun 2022 04:30:46 +0000 (04:30 +0000)
committerdjm <djm@openbsd.org>
Fri, 3 Jun 2022 04:30:46 +0000 (04:30 +0000)
sshd_config; previously if the same name was reused then the last
would win (which is the opposite to how the config is supposed to
work).

While there, make the ssh_config parsing more like sshd_config.

bz3438, ok dtucker

usr.bin/ssh/clientloop.c
usr.bin/ssh/misc.c
usr.bin/ssh/misc.h
usr.bin/ssh/mux.c
usr.bin/ssh/readconf.c
usr.bin/ssh/readconf.h
usr.bin/ssh/servconf.c

index 8807d23..af5c676 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: clientloop.c,v 1.379 2022/04/20 04:19:11 djm Exp $ */
+/* $OpenBSD: clientloop.c,v 1.380 2022/06/03 04:30:46 djm Exp $ */
 /*
  * Author: Tatu Ylonen <ylo@cs.hut.fi>
  * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -2452,7 +2452,8 @@ client_session2_setup(struct ssh *ssh, int id, int want_tty, int want_subsystem,
     const char *term, struct termios *tiop, int in_fd, struct sshbuf *cmd,
     char **env)
 {
-       int i, j, matched, len, r;
+       size_t i, j, len;
+       int matched, r;
        char *name, *val;
        Channel *c = NULL;
 
@@ -2535,13 +2536,13 @@ client_session2_setup(struct ssh *ssh, int id, int want_tty, int want_subsystem,
                        len = 900;
                if (want_subsystem) {
                        debug("Sending subsystem: %.*s",
-                           len, (const u_char*)sshbuf_ptr(cmd));
+                           (int)len, (const u_char*)sshbuf_ptr(cmd));
                        channel_request_start(ssh, id, "subsystem", 1);
                        client_expect_confirm(ssh, id, "subsystem",
                            CONFIRM_CLOSE);
                } else {
                        debug("Sending command: %.*s",
-                           len, (const u_char*)sshbuf_ptr(cmd));
+                           (int)len, (const u_char*)sshbuf_ptr(cmd));
                        channel_request_start(ssh, id, "exec", 1);
                        client_expect_confirm(ssh, id, "exec", CONFIRM_CLOSE);
                }
index 287f031..a864b87 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: misc.c,v 1.175 2022/03/20 08:51:21 djm Exp $ */
+/* $OpenBSD: misc.c,v 1.176 2022/06/03 04:30:47 djm Exp $ */
 /*
  * Copyright (c) 2000 Markus Friedl.  All rights reserved.
  * Copyright (c) 2005-2020 Damien Miller.  All rights reserved.
@@ -2691,3 +2691,20 @@ lookup_env_in_list(const char *env, char * const *envs, size_t nenvs)
        }
        return NULL;
 }
+
+const char *
+lookup_setenv_in_list(const char *env, char * const *envs, size_t nenvs)
+{
+       char *name, *cp;
+       const char *ret;
+
+       name = xstrdup(env);
+       if ((cp = strchr(name, '=')) == NULL) {
+               free(name);
+               return NULL; /* not env=val */
+       }
+       *cp = '\0';
+       ret = lookup_env_in_list(name, envs, nenvs);
+       free(name);
+       return ret;
+}
index f4f26c2..5ca5dde 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: misc.h,v 1.99 2021/11/13 21:14:13 deraadt Exp $ */
+/* $OpenBSD: misc.h,v 1.100 2022/06/03 04:30:47 djm Exp $ */
 
 /*
  * Author: Tatu Ylonen <ylo@cs.hut.fi>
@@ -177,6 +177,8 @@ void         child_set_env(char ***envp, u_int *envsizep, const char *name,
            const char *value);
 const char *lookup_env_in_list(const char *env,
            char * const *envs, size_t nenvs);
+const char *lookup_setenv_in_list(const char *env,
+           char * const *envs, size_t nenvs);
 
 int     argv_split(const char *, int *, char ***, int);
 char   *argv_assemble(int, char **argv);
index fb5abc0..6c36377 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: mux.c,v 1.93 2022/05/05 00:55:11 djm Exp $ */
+/* $OpenBSD: mux.c,v 1.94 2022/06/03 04:30:47 djm Exp $ */
 /*
  * Copyright (c) 2002-2008 Damien Miller <djm@openbsd.org>
  *
@@ -229,7 +229,8 @@ mux_master_control_cleanup_cb(struct ssh *ssh, int cid, void *unused)
 static int
 env_permitted(const char *env)
 {
-       int i, ret;
+       u_int i;
+       int ret;
        char name[1024], *cp;
 
        if ((cp = strchr(env, '=')) == NULL || cp == env)
@@ -1846,9 +1847,9 @@ mux_client_request_session(int fd)
        struct sshbuf *m;
        char *e;
        const char *term = NULL;
-       u_int echar, rid, sid, esid, exitval, type, exitval_seen;
+       u_int i, echar, rid, sid, esid, exitval, type, exitval_seen;
        extern char **environ;
-       int r, i, rawmode;
+       int r, rawmode;
 
        debug3_f("entering");
 
index f46a0f8..5b5afa8 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: readconf.c,v 1.367 2022/04/20 15:56:49 millert Exp $ */
+/* $OpenBSD: readconf.c,v 1.368 2022/06/03 04:30:47 djm Exp $ */
 /*
  * Author: Tatu Ylonen <ylo@cs.hut.fi>
  * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -739,7 +739,7 @@ match_cfg_line(Options *options, char **condition, struct passwd *pw,
 static void
 rm_env(Options *options, const char *arg, const char *filename, int linenum)
 {
-       int i, j, onum_send_env = options->num_send_env;
+       u_int i, j, onum_send_env = options->num_send_env;
 
        /* Remove an environment variable */
        for (i = 0; i < options->num_send_env; ) {
@@ -1719,20 +1719,10 @@ parse_pubkey_algos:
                                /* Removing an env var */
                                rm_env(options, arg, filename, linenum);
                                continue;
-                       } else {
-                               /* Adding an env var */
-                               if (options->num_send_env >= INT_MAX) {
-                                       error("%s line %d: too many send env.",
-                                           filename, linenum);
-                                       goto out;
-                               }
-                               options->send_env = xrecallocarray(
-                                   options->send_env, options->num_send_env,
-                                   options->num_send_env + 1,
-                                   sizeof(*options->send_env));
-                               options->send_env[options->num_send_env++] =
-                                   xstrdup(arg);
                        }
+                       opt_array_append(filename, linenum,
+                           lookup_opcode_name(opcode),
+                           &options->send_env, &options->num_send_env, arg);
                }
                break;
 
@@ -1746,16 +1736,15 @@ parse_pubkey_algos:
                        }
                        if (!*activep || value != 0)
                                continue;
-                       /* Adding a setenv var */
-                       if (options->num_setenv >= INT_MAX) {
-                               error("%s line %d: too many SetEnv.",
-                                   filename, linenum);
-                               goto out;
+                       if (lookup_setenv_in_list(arg, options->setenv,
+                           options->num_setenv) != NULL) {
+                               debug2("%s line %d: ignoring duplicate env "
+                                   "name \"%.64s\"", filename, linenum, arg);
+                               continue;
                        }
-                       options->setenv = xrecallocarray(
-                           options->setenv, options->num_setenv,
-                           options->num_setenv + 1, sizeof(*options->setenv));
-                       options->setenv[options->num_setenv++] = xstrdup(arg);
+                       opt_array_append(filename, linenum,
+                           lookup_opcode_name(opcode),
+                           &options->setenv, &options->num_setenv, arg);
                }
                break;
 
@@ -2749,9 +2738,9 @@ free_options(Options *o)
        }
        free(o->remote_forwards);
        free(o->stdio_forward_host);
-       FREE_ARRAY(int, o->num_send_env, o->send_env);
+       FREE_ARRAY(u_int, o->num_send_env, o->send_env);
        free(o->send_env);
-       FREE_ARRAY(int, o->num_setenv, o->setenv);
+       FREE_ARRAY(u_int, o->num_setenv, o->setenv);
        free(o->setenv);
        free(o->control_path);
        free(o->local_command);
index ded13c9..f647bd4 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: readconf.h,v 1.146 2021/12/19 22:14:47 djm Exp $ */
+/* $OpenBSD: readconf.h,v 1.147 2022/06/03 04:30:47 djm Exp $ */
 
 /*
  * Author: Tatu Ylonen <ylo@cs.hut.fi>
@@ -124,10 +124,10 @@ typedef struct {
        int     server_alive_interval;
        int     server_alive_count_max;
 
-       int     num_send_env;
-       char   **send_env;
-       int     num_setenv;
-       char   **setenv;
+       u_int   num_send_env;
+       char    **send_env;
+       u_int   num_setenv;
+       char    **setenv;
 
        char    *control_path;
        int     control_master;
index f681c2f..f7317a5 100644 (file)
@@ -1,5 +1,5 @@
 
-/* $OpenBSD: servconf.c,v 1.384 2022/03/18 04:04:11 djm Exp $ */
+/* $OpenBSD: servconf.c,v 1.385 2022/06/03 04:30:47 djm Exp $ */
 /*
  * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
  *                    All rights reserved
@@ -1976,6 +1976,12 @@ process_server_config_line_depth(ServerOptions *options, char *line,
                                    filename, linenum);
                        if (!*activep || uvalue != 0)
                                continue;
+                       if (lookup_setenv_in_list(arg, options->setenv,
+                           options->num_setenv) != NULL) {
+                               debug2("%s line %d: ignoring duplicate env "
+                                   "name \"%.64s\"", filename, linenum, arg);
+                               continue;
+                       }
                        opt_array_append(filename, linenum, keyword,
                            &options->setenv, &options->num_setenv, arg);
                }