Skip to content

Commit f37879f

Browse files
author
Peter Szabo
committed
added AcceptEnv (-A) support to pass environment variables from the client to the server
1 parent 5d0cc9a commit f37879f

File tree

5 files changed

+70
-6
lines changed

5 files changed

+70
-6
lines changed

c.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ ls -l dropbearmulti
1515
#
1616
# $ ssh-keygen -t rsa -b 4096 -N '' -C hostkey_rsa4096 -f hostkey_rsa4096
1717
# $ ./dropbearmulti dropbearconvert openssh dropbear hostkey_rsa4096 dropbear_hostkey_rsa4096
18-
# $ ./dropbearmulti dropbear -r dropbear_hostkey_rsa4096 -F -E -m -s -P '' -p 65522
18+
# $ ./dropbearmulti dropbear -r dropbear_hostkey_rsa4096 -F -E -m -s -P '' -A WINDOW=,TZ=,COLORFGBG=,LANG=,LC_ -p 65522
1919
# ...
2020
# $ ssh -v -o UserKnownHostsFile=/dev/null -o GlobalKnownHostsFile=/dev/null -o IdentitiesOnly=yes -o StrictHostKeyChecking=no -F /dev/null -i ... -p 65522 127.0.0.1 id
2121
#

chansession.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,10 @@ struct ChanSess {
7676
#ifdef ENABLE_SVR_PUBKEY_OPTIONS
7777
char *original_command;
7878
#endif
79+
80+
unsigned env_capacity;
81+
unsigned env_size;
82+
char **env;
7983
};
8084

8185
struct ChildPid {

runopts.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,8 @@ typedef struct svr_runopts {
120120
buffer * banner;
121121
char * pidfile;
122122

123+
char *acceptenv; /* Comma-separated. */
124+
123125
} svr_runopts;
124126

125127
extern svr_runopts svr_opts;

svr-chansession.c

Lines changed: 58 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,8 @@ static void send_msg_chansess_exitstatus(struct Channel * channel,
6161
static void send_msg_chansess_exitsignal(struct Channel * channel,
6262
struct ChanSess * chansess);
6363
static void get_termmodes(struct ChanSess *chansess);
64+
static char *create_newvar(const char *param, const char *var);
65+
6466

6567
const struct ChanType svrchansess = {
6668
0, /* sepfds */
@@ -305,6 +307,12 @@ static void closechansess(struct Channel *channel) {
305307
m_free(chansess->original_command);
306308
#endif
307309

310+
if (chansess->env) {
311+
char **p = chansess->env;
312+
for (; *p; free(*p++)) {}
313+
m_free(chansess->env);
314+
}
315+
308316
if (chansess->tty) {
309317
/* write the utmp/wtmp login record */
310318
li = chansess_login_alloc(chansess);
@@ -339,6 +347,25 @@ static void closechansess(struct Channel *channel) {
339347
TRACE(("leave closechansess"))
340348
}
341349

350+
static char is_env_allowed(const char *name) {
351+
char const *p = svr_opts.acceptenv, *q;
352+
if (!name || name[0] == '\0' || strchr(name, '=')) return 0;
353+
/* Comma-separated, LC_ means prefix, TZ= means 1 var. */
354+
if (p) for (; *p != '\0'; ) {
355+
for (q = p; *q != '\0' && *q != ','; ++q) {}
356+
if (p != q) {
357+
if (q[-1] == '=') {
358+
const unsigned size = q - p - 1;
359+
if (0 == memcmp(name, p, size) && name[size] == '\0') return 1;
360+
} else {
361+
if (0 == strncmp(name, p, q - p)) return 1; /* Prefix match. */
362+
}
363+
}
364+
p = q + 1;
365+
}
366+
return 0;
367+
}
368+
342369
/* Handle requests for a channel. These can be execution requests,
343370
* or x11/authagent forwarding. These are passed to appropriate handlers */
344371
static void chansessionrequest(struct Channel *channel) {
@@ -383,8 +410,25 @@ static void chansessionrequest(struct Channel *channel) {
383410
#endif
384411
} else if (strcmp(type, "signal") == 0) {
385412
ret = sessionsignal(chansess);
413+
} else if (strcmp(type, "env") == 0) {
414+
char *name = buf_getstring(ses.payload, NULL);
415+
char *value = buf_getstring(ses.payload, NULL);
416+
if (name && value && is_env_allowed(name)) {
417+
char *newvar = create_newvar(name, value);
418+
if (chansess->env_size + 1 >= chansess->env_capacity) {
419+
if (chansess->env) {
420+
chansess->env = m_realloc(chansess->env, sizeof(*chansess->env) * (chansess->env_capacity <<= 1));
421+
} else {
422+
chansess->env = m_malloc(sizeof(*chansess->env) * (chansess->env_capacity = 16));
423+
}
424+
}
425+
chansess->env[chansess->env_size++] = newvar; /* Takes ownership. */
426+
chansess->env[chansess->env_size] = NULL;
427+
}
428+
m_free(value);
429+
m_free(name);
386430
} else {
387-
/* etc, todo "env", "subsystem" */
431+
/* etc */
388432
}
389433

390434
out:
@@ -943,6 +987,12 @@ static void execchild(void *user_data) {
943987
}
944988
}
945989

990+
/* Call putenv here first, so "USER" etc. below will override it. */
991+
if (chansess->env) {
992+
char **p = chansess->env;
993+
for (; *p; putenv(*p++)) {}
994+
}
995+
946996
/* set env vars */
947997
addnewvar("USER", ses.authstate.pw_name);
948998
addnewvar("LOGNAME", ses.authstate.pw_name);
@@ -1013,9 +1063,7 @@ void svr_chansessinitialise() {
10131063

10141064
}
10151065

1016-
/* add a new environment variable, allocating space for the entry */
1017-
void addnewvar(const char* param, const char* var) {
1018-
1066+
static char *create_newvar(const char *param, const char *var) {
10191067
char* newvar = NULL;
10201068
int plen, vlen;
10211069

@@ -1027,8 +1075,13 @@ void addnewvar(const char* param, const char* var) {
10271075
newvar[plen] = '=';
10281076
memcpy(&newvar[plen+1], var, vlen);
10291077
newvar[plen+vlen+1] = '\0';
1078+
return newvar;
1079+
}
1080+
1081+
/* add a new environment variable, allocating space for the entry */
1082+
void addnewvar(const char* param, const char* var) {
10301083
/* newvar is leaked here, but that's part of putenv()'s semantics */
1031-
if (putenv(newvar) < 0) {
1084+
if (putenv(create_newvar(param, var)) < 0) {
10321085
dropbear_exit("environ error");
10331086
}
10341087
}

svr-runopts.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@ static void printhelp(const char * progname) {
9696
" (default %d, larger may be faster, max 1MB)\n"
9797
"-K keepalive (0 is never, default %d, in seconds)\n"
9898
"-I idle_timeout (0 is never, default %d, in seconds)\n"
99+
"-A env1=,env2 Environment varialbe names and prefixes to accept\n"
99100
"-V Print version and exit.\n"
100101
#ifdef DEBUG_TRACE
101102
"-v verbose (compiled with DEBUG_TRACE)\n"
@@ -139,6 +140,7 @@ void svr_getopts(int argc, char ** argv) {
139140
svr_opts.inetdmode = 0;
140141
svr_opts.portcount = 0;
141142
svr_opts.hostkey = NULL;
143+
svr_opts.acceptenv = NULL;
142144
#ifndef NOSYSHOSTKEYLOAD
143145
#ifdef DROPBEAR_DELAY_HOSTKEY
144146
svr_opts.delay_hostkey = 0;
@@ -191,6 +193,9 @@ void svr_getopts(int argc, char ** argv) {
191193
case 'r':
192194
next = &keyfile;
193195
break;
196+
case 'A':
197+
next = &svr_opts.acceptenv;
198+
break;
194199
#ifndef NOSYSHOSTKEYLOAD
195200
#ifdef DROPBEAR_DELAY_HOSTKEY
196201
case 'R':

0 commit comments

Comments
 (0)