Skip to content
Permalink
Browse files Browse the repository at this point in the history
redo the environment inheritance to not inherit. it was intended to m…
…ake life easier, but it can be surprising or even unsafe. instead, reset just about everything to the target user's values. ok deraadt martijn Thanks to Sander Bos in particular for pointing out some nasty edge cases.
  • Loading branch information
tedu authored and Duncaen committed Oct 19, 2019
1 parent dbc7d06 commit 01c658f
Show file tree
Hide file tree
Showing 4 changed files with 42 additions and 22 deletions.
4 changes: 3 additions & 1 deletion doas.c
Expand Up @@ -449,6 +449,7 @@ main(int argc, char **argv)

#ifdef HAVE_SETUSERCONTEXT
if (setusercontext(NULL, targpw, target, LOGIN_SETGROUP |
LOGIN_SETPATH |
LOGIN_SETPRIORITY | LOGIN_SETRESOURCES | LOGIN_SETUMASK |
LOGIN_SETUSER) != 0)
errx(1, "failed to set user context for target");
Expand Down Expand Up @@ -479,9 +480,10 @@ main(int argc, char **argv)
syslog(LOG_AUTHPRIV | LOG_INFO, "%s ran command %s as %s from %s",
mypw->pw_name, cmdline, targpw->pw_name, cwd);

envp = prepenv(rule);
envp = prepenv(rule, mypw, targpw);

if (rule->cmd) {
/* do this again after setusercontext reset it */
if (setenv("PATH", safepath, 1) == -1)
err(1, "failed to set PATH '%s'", safepath);
}
Expand Down
10 changes: 2 additions & 8 deletions doas.conf.5
Expand Up @@ -51,15 +51,9 @@ again for some time.
.It Ic keepenv
The user's environment is maintained.
The default is to reset the environment, except for the variables
.Ev DISPLAY ,
.Ev HOME ,
.Ev LOGNAME ,
.Ev MAIL ,
.Ev PATH ,
.Ev TERM ,
.Ev USER
.Ev DISPLAY
and
.Ev USERNAME .
.Ev TERM .
.It Ic setenv { Oo Ar variable ... Oc Oo Ar variable=value ... Oc Ic }
In addition to the variables mentioned above, keep the space-separated
specified variables.
Expand Down
5 changes: 4 additions & 1 deletion doas.h
Expand Up @@ -29,7 +29,10 @@ extern struct rule **rules;
extern int nrules;
extern int parse_errors;

char **prepenv(const struct rule *);
struct passwd;

char **prepenv(const struct rule *, const struct passwd *,
const struct passwd *);

#define PERMIT 1
#define DENY 2
Expand Down
45 changes: 33 additions & 12 deletions env.c
Expand Up @@ -24,6 +24,7 @@
#include <err.h>
#include <unistd.h>
#include <errno.h>
#include <pwd.h>

#include "doas.h"
#include "includes.h"
Expand All @@ -39,6 +40,8 @@ struct env {
u_int count;
};

static void fillenv(struct env *env, const char **envlist);

static int
envcmp(struct envnode *a, struct envnode *b)
{
Expand Down Expand Up @@ -69,8 +72,19 @@ freenode(struct envnode *node)
free(node);
}

static void
addnode(struct env *env, const char *key, const char *value)
{
struct envnode *node;

node = createnode(key, value);
RB_INSERT(envtree, &env->root, node);
env->count++;
}

static struct env *
createenv(const struct rule *rule)
createenv(const struct rule *rule, const struct passwd *mypw,
const struct passwd *targpw)
{
struct env *env;
u_int i;
Expand All @@ -81,6 +95,8 @@ createenv(const struct rule *rule)
RB_INIT(&env->root);
env->count = 0;

addnode(env, "DOAS_USER", mypw->pw_name);

if (rule->options & KEEPENV) {
extern char **environ;

Expand Down Expand Up @@ -109,6 +125,19 @@ createenv(const struct rule *rule)
env->count++;
}
}
} else {
static const char *copyset[] = {
"DISPLAY", "TERM",
NULL
};

addnode(env, "HOME", targpw->pw_dir);
addnode(env, "LOGNAME", targpw->pw_name);
addnode(env, "PATH", getenv("PATH"));
addnode(env, "SHELL", targpw->pw_shell);
addnode(env, "USER", targpw->pw_name);

fillenv(env, copyset);
}

return env;
Expand Down Expand Up @@ -187,20 +216,12 @@ fillenv(struct env *env, const char **envlist)
}

char **
prepenv(const struct rule *rule)
prepenv(const struct rule *rule, const struct passwd *mypw,
const struct passwd *targpw)
{
static const char *safeset[] = {
"DISPLAY", "HOME", "LOGNAME", "MAIL",
"PATH", "TERM", "USER", "USERNAME",
NULL
};
struct env *env;

env = createenv(rule);

/* if we started with blank, fill some defaults then apply rules */
if (!(rule->options & KEEPENV))
fillenv(env, safeset);
env = createenv(rule, mypw, targpw);
if (rule->envlist)
fillenv(env, rule->envlist);

Expand Down

0 comments on commit 01c658f

Please sign in to comment.