From 61a2c1da308b9d0843669e803a9bbc3cbf77a89c Mon Sep 17 00:00:00 2001 From: dtucker Date: Sun, 2 May 2004 12:11:30 +0000 Subject: [PATCH] - djm@cvs.openbsd.org 2004/04/27 09:46:37 [readconf.c readconf.h servconf.c servconf.h session.c session.h ssh.c ssh_config.5 sshd_config.5] bz #815: implement ability to pass specified environment variables from the client to the server; ok markus@ --- ChangeLog | 5 +++++ readconf.c | 18 +++++++++++++++++- readconf.h | 7 ++++++- servconf.c | 19 +++++++++++++++++-- servconf.h | 6 +++++- session.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++- session.h | 7 ++++++- ssh.c | 41 +++++++++++++++++++++++++++++++++++++++- ssh_config.5 | 23 ++++++++++++++++++++++- sshd_config.5 | 25 ++++++++++++++++++++++++- 10 files changed, 193 insertions(+), 10 deletions(-) diff --git a/ChangeLog b/ChangeLog index 33f452c5..4b865fdc 100644 --- a/ChangeLog +++ b/ChangeLog @@ -4,6 +4,11 @@ [moduli.c] Bugzilla #850: Sophie Germain is the correct name of the French mathematician, "Sophie Germaine" isn't; from Luc.Maisonobe@c-s.fr + - djm@cvs.openbsd.org 2004/04/27 09:46:37 + [readconf.c readconf.h servconf.c servconf.h session.c session.h ssh.c + ssh_config.5 sshd_config.5] + bz #815: implement ability to pass specified environment variables from + the client to the server; ok markus@ 20040423 - (dtucker) [configure.ac openbsd-compat/getrrsetbyname.c] Declare h_errno diff --git a/readconf.c b/readconf.c index 096d1a71..f4710e83 100644 --- a/readconf.c +++ b/readconf.c @@ -12,7 +12,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: readconf.c,v 1.129 2004/04/18 23:10:26 djm Exp $"); +RCSID("$OpenBSD: readconf.c,v 1.130 2004/04/27 09:46:36 djm Exp $"); #include "ssh.h" #include "xmalloc.h" @@ -106,6 +106,7 @@ typedef enum { oEnableSSHKeysign, oRekeyLimit, oVerifyHostKeyDNS, oConnectTimeout, oAddressFamily, oGssAuthentication, oGssDelegateCreds, oServerAliveInterval, oServerAliveCountMax, oIdentitiesOnly, + oSendEnv, oDeprecated, oUnsupported } OpCodes; @@ -193,6 +194,7 @@ static struct { { "addressfamily", oAddressFamily }, { "serveraliveinterval", oServerAliveInterval }, { "serveralivecountmax", oServerAliveCountMax }, + { "sendenv", oSendEnv }, { NULL, oBadOption } }; @@ -749,6 +751,19 @@ parse_int: intptr = &options->server_alive_count_max; goto parse_int; + case oSendEnv: + while ((arg = strdelim(&s)) != NULL && *arg != '\0') { + if (strchr(arg, '=') != NULL) + fatal("%s line %d: Invalid environment name.", + filename, linenum); + if (options->num_send_env >= MAX_SEND_ENV) + fatal("%s line %d: too many send env.", + filename, linenum); + options->send_env[options->num_send_env++] = + xstrdup(arg); + } + break; + case oDeprecated: debug("%s line %d: Deprecated option \"%s\"", filename, linenum, keyword); @@ -894,6 +909,7 @@ initialize_options(Options * options) options->verify_host_key_dns = -1; options->server_alive_interval = -1; options->server_alive_count_max = -1; + options->num_send_env = 0; } /* diff --git a/readconf.h b/readconf.h index 9d70fee6..66805594 100644 --- a/readconf.h +++ b/readconf.h @@ -1,4 +1,4 @@ -/* $OpenBSD: readconf.h,v 1.61 2004/04/18 23:10:26 djm Exp $ */ +/* $OpenBSD: readconf.h,v 1.62 2004/04/27 09:46:37 djm Exp $ */ /* * Author: Tatu Ylonen @@ -27,6 +27,8 @@ typedef struct { } Forward; /* Data structure for representing option data. */ +#define MAX_SEND_ENV 256 + typedef struct { int forward_agent; /* Forward authentication agent. */ int forward_x11; /* Forward X11 display. */ @@ -103,6 +105,9 @@ typedef struct { int identities_only; int server_alive_interval; int server_alive_count_max; + + int num_send_env; + char *send_env[MAX_SEND_ENV]; } Options; diff --git a/servconf.c b/servconf.c index a72246b6..ae380f52 100644 --- a/servconf.c +++ b/servconf.c @@ -10,7 +10,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: servconf.c,v 1.130 2003/12/23 16:12:10 jakob Exp $"); +RCSID("$OpenBSD: servconf.c,v 1.131 2004/04/27 09:46:37 djm Exp $"); #include "ssh.h" #include "log.h" @@ -101,6 +101,7 @@ initialize_server_options(ServerOptions *options) options->client_alive_count_max = -1; options->authorized_keys_file = NULL; options->authorized_keys_file2 = NULL; + options->num_accept_env = 0; /* Needs to be accessable in many places */ use_privsep = -1; @@ -266,7 +267,7 @@ typedef enum { sBanner, sUseDNS, sHostbasedAuthentication, sHostbasedUsesNameFromPacketOnly, sClientAliveInterval, sClientAliveCountMax, sAuthorizedKeysFile, sAuthorizedKeysFile2, - sGssAuthentication, sGssCleanupCreds, + sGssAuthentication, sGssCleanupCreds, sAcceptEnv, sUsePrivilegeSeparation, sDeprecated, sUnsupported } ServerOpCodes; @@ -366,6 +367,7 @@ static struct { { "authorizedkeysfile", sAuthorizedKeysFile }, { "authorizedkeysfile2", sAuthorizedKeysFile2 }, { "useprivilegeseparation", sUsePrivilegeSeparation}, + { "acceptenv", sAcceptEnv }, { NULL, sBadOption } }; @@ -892,6 +894,19 @@ parse_flag: intptr = &options->client_alive_count_max; goto parse_int; + case sAcceptEnv: + while ((arg = strdelim(&cp)) && *arg != '\0') { + if (strchr(arg, '=') != NULL) + fatal("%s line %d: Invalid environment name.", + filename, linenum); + if (options->num_accept_env >= MAX_ACCEPT_ENV) + fatal("%s line %d: too many allow env.", + filename, linenum); + options->accept_env[options->num_accept_env++] = + xstrdup(arg); + } + break; + case sDeprecated: logit("%s line %d: Deprecated option %s", filename, linenum, arg); diff --git a/servconf.h b/servconf.h index 57c7e5fa..1c6296ac 100644 --- a/servconf.h +++ b/servconf.h @@ -1,4 +1,4 @@ -/* $OpenBSD: servconf.h,v 1.67 2003/12/23 16:12:10 jakob Exp $ */ +/* $OpenBSD: servconf.h,v 1.68 2004/04/27 09:46:37 djm Exp $ */ /* * Author: Tatu Ylonen @@ -24,6 +24,7 @@ #define MAX_DENY_GROUPS 256 /* Max # groups on deny list. */ #define MAX_SUBSYSTEMS 256 /* Max # subsystems. */ #define MAX_HOSTKEYS 256 /* Max # hostkeys. */ +#define MAX_ACCEPT_ENV 256 /* Max # of env vars. */ /* permit_root_login */ #define PERMIT_NOT_SET -1 @@ -107,6 +108,9 @@ typedef struct { char *subsystem_name[MAX_SUBSYSTEMS]; char *subsystem_command[MAX_SUBSYSTEMS]; + u_int num_accept_env; + char *accept_env[MAX_ACCEPT_ENV]; + int max_startups_begin; int max_startups_rate; int max_startups; diff --git a/session.c b/session.c index 55db2ffd..da11e554 100644 --- a/session.c +++ b/session.c @@ -33,7 +33,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: session.c,v 1.172 2004/01/30 09:48:57 markus Exp $"); +RCSID("$OpenBSD: session.c,v 1.173 2004/04/27 09:46:37 djm Exp $"); #include "ssh.h" #include "ssh1.h" @@ -42,6 +42,7 @@ RCSID("$OpenBSD: session.c,v 1.172 2004/01/30 09:48:57 markus Exp $"); #include "sshpty.h" #include "packet.h" #include "buffer.h" +#include "match.h" #include "mpaux.h" #include "uidswap.h" #include "compat.h" @@ -996,6 +997,10 @@ do_setup_env(Session *s, const char *shell) if (!options.use_login) { /* Set basic environment. */ + for (i = 0; i < s->num_env; i++) + child_set_env(&env, &envsize, s->env[i].name, + s->env[i].val); + child_set_env(&env, &envsize, "USER", pw->pw_name); child_set_env(&env, &envsize, "LOGNAME", pw->pw_name); #ifdef _AIX @@ -1831,6 +1836,41 @@ session_break_req(Session *s) return 1; } +static int +session_env_req(Session *s) +{ + char *name, *val; + u_int name_len, val_len, i; + + name = packet_get_string(&name_len); + val = packet_get_string(&val_len); + packet_check_eom(); + + /* Don't set too many environment variables */ + if (s->num_env > 128) { + debug2("Ignoring env request %s: too many env vars", name); + goto fail; + } + + for (i = 0; i < options.num_accept_env; i++) { + if (match_pattern(name, options.accept_env[i])) { + debug2("Setting env %d: %s=%s", s->num_env, name, val); + s->env = xrealloc(s->env, sizeof(*s->env) * + (s->num_env + 1)); + s->env[s->num_env].name = name; + s->env[s->num_env].val = val; + s->num_env++; + return (1); + } + } + debug2("Ignoring env request %s: disallowed name", name); + + fail: + xfree(name); + xfree(val); + return (0); +} + static int session_auth_agent_req(Session *s) { @@ -1880,6 +1920,8 @@ session_input_channel_req(Channel *c, const char *rtype) success = session_subsystem_req(s); } else if (strcmp(rtype, "break") == 0) { success = session_break_req(s); + } else if (strcmp(rtype, "env") == 0) { + success = session_env_req(s); } } if (strcmp(rtype, "window-change") == 0) { @@ -2017,6 +2059,8 @@ session_exit_message(Session *s, int status) void session_close(Session *s) { + int i; + debug("session_close: session %d pid %ld", s->self, (long)s->pid); if (s->ttyfd != -1) session_pty_cleanup(s); @@ -2031,6 +2075,12 @@ session_close(Session *s) if (s->auth_proto) xfree(s->auth_proto); s->used = 0; + for (i = 0; i < s->num_env; i++) { + xfree(s->env[i].name); + xfree(s->env[i].val); + } + if (s->env != NULL) + xfree(s->env); session_proctitle(s); } diff --git a/session.h b/session.h index 405b8fe8..e5250665 100644 --- a/session.h +++ b/session.h @@ -1,4 +1,4 @@ -/* $OpenBSD: session.h,v 1.21 2003/09/23 20:17:11 markus Exp $ */ +/* $OpenBSD: session.h,v 1.22 2004/04/27 09:46:37 djm Exp $ */ /* * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. @@ -53,6 +53,11 @@ struct Session { /* proto 2 */ int chanid; int is_subsystem; + int num_env; + struct { + char *name; + char *val; + } *env; }; void do_authenticated(Authctxt *); diff --git a/ssh.c b/ssh.c index 9658e4af..df3b64b1 100644 --- a/ssh.c +++ b/ssh.c @@ -40,7 +40,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: ssh.c,v 1.211 2004/04/19 21:51:49 djm Exp $"); +RCSID("$OpenBSD: ssh.c,v 1.212 2004/04/27 09:46:37 djm Exp $"); #include #include @@ -68,6 +68,7 @@ RCSID("$OpenBSD: ssh.c,v 1.211 2004/04/19 21:51:49 djm Exp $"); #include "kex.h" #include "mac.h" #include "sshtty.h" +#include "match.h" #ifdef SMARTCARD #include "scard.h" @@ -1057,6 +1058,44 @@ ssh_session2_setup(int id, void *arg) packet_send(); } + /* Transfer any environment variables from client to server */ + if (options.num_send_env != 0) { + int i, j, matched; + extern char **environ; + char *name, *val; + + debug("Sending environment."); + for (i = 0; environ && environ[i] != NULL; i++) { + /* Split */ + name = xstrdup(environ[i]); + if ((val = strchr(name, '=')) == NULL) { + free(name); + continue; + } + *val++ = '\0'; + + matched = 0; + for (j = 0; j < options.num_send_env; j++) { + if (match_pattern(name, options.send_env[j])) { + matched = 1; + break; + } + } + if (!matched) { + debug3("Ignored env %s", name); + free(name); + continue; + } + + debug("Sending env %s = %s", name, val); + channel_request_start(id, "env", 0); + packet_put_cstring(name); + packet_put_cstring(val); + packet_send(); + free(name); + } + } + len = buffer_len(&command); if (len > 0) { if (len > 900) diff --git a/ssh_config.5 b/ssh_config.5 index df479c63..fbe8c657 100644 --- a/ssh_config.5 +++ b/ssh_config.5 @@ -34,7 +34,7 @@ .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .\" -.\" $OpenBSD: ssh_config.5,v 1.31 2004/04/19 16:12:14 jmc Exp $ +.\" $OpenBSD: ssh_config.5,v 1.32 2004/04/27 09:46:37 djm Exp $ .Dd September 25, 1999 .Dt SSH_CONFIG 5 .Os @@ -570,6 +570,27 @@ running. The default is .Dq yes . Note that this option applies to protocol version 1 only. +.It Cm SendEnv +Specifies what variables from the local +.Xr environ 7 +should be sent to the server. +Note that environment passing is only supported for protocol 2, the +server must also support it and must be configured to accept these +enviornment variables. +Refer to +.Cm AcceptEnv +in +.Xr sshd_config 5 +for how to configure the server. +Variables are specified by name, which may contain the wildcard characters +.Ql \&* +and +.Ql \&? . +Multiple environment variables may be seperated by whitespace or spread +across multiple +.Cm SendEnv +directives. +The default is not to send any environment variables. .It Cm ServerAliveInterval Sets a timeout interval in seconds after which if no data has been received from the server, diff --git a/sshd_config.5 b/sshd_config.5 index e15a225f..b702e5ad 100644 --- a/sshd_config.5 +++ b/sshd_config.5 @@ -34,7 +34,7 @@ .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .\" -.\" $OpenBSD: sshd_config.5,v 1.29 2004/03/08 10:18:57 dtucker Exp $ +.\" $OpenBSD: sshd_config.5,v 1.30 2004/04/27 09:46:37 djm Exp $ .Dd September 25, 1999 .Dt SSHD_CONFIG 5 .Os @@ -61,6 +61,29 @@ The possible keywords and their meanings are as follows (note that keywords are case-insensitive and arguments are case-sensitive): .Bl -tag -width Ds +.It Cm AcceptEnv +Specifies what environment variables sent by the client will be copied into +the session's +.Xr environ 7 . +See +.Cm SendEnv +in +.Xr ssh_config 5 +for how to configure the client. +Note that environment passingis only supported for protocol 2. +Variables are specified by name, which may contain the wildcard characters +.Ql \&* +and +.Ql \&? . +Multiple environment variables may be seperated by whitespace or spread +across multiple +.Cm AcceptEnv +directives. +Be warned that some enviornment variables could be used to bypass restricted +user environments. +For this reason, care should be taken in the use of this directive. +The default is not to accept any environment variables. +.Pp .It Cm AllowGroups This keyword can be followed by a list of group name patterns, separated by spaces. -- 2.45.2