opendoas

my fork of doas with custom prompt
git clone git://git.kocotian.pl/opendoas.git
Log | Files | Refs | README | LICENSE

commit 01c658f8c45cb92a343be5f32aa6da70b2032168
parent dbc7d06b5bbf01652744423bd8825ea7b5e92f73
Author: tedu <tedu>
Date:   Sun, 16 Jun 2019 18:16:34 +0000

redo the environment inheritance to not inherit. it was intended to make 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.

Diffstat:
Mdoas.c | 4+++-
Mdoas.conf.5 | 10++--------
Mdoas.h | 5++++-
Menv.c | 45+++++++++++++++++++++++++++++++++------------
4 files changed, 42 insertions(+), 22 deletions(-)

diff --git a/doas.c b/doas.c @@ -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"); @@ -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); } diff --git a/doas.conf.5 b/doas.conf.5 @@ -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. diff --git a/doas.h b/doas.h @@ -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 diff --git a/env.c b/env.c @@ -24,6 +24,7 @@ #include <err.h> #include <unistd.h> #include <errno.h> +#include <pwd.h> #include "doas.h" #include "includes.h" @@ -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) { @@ -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; @@ -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; @@ -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; @@ -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);