3 * Copyright (c) 2016 Ted Unangst <tedu@openbsd.org>
5 * Permission to use, copy, modify, and distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
20 #include <sys/types.h>
34 const char *formerpath;
37 RB_ENTRY(envnode) node;
43 RB_HEAD(envtree, envnode) root;
47 static void fillenv(struct env *env, const char **envlist);
50 envcmp(struct envnode *a, struct envnode *b)
52 return strcmp(a->key, b->key);
54 RB_GENERATE_STATIC(envtree, envnode, node, envcmp)
56 static struct envnode *
57 createnode(const char *key, const char *value)
61 node = malloc(sizeof(*node));
64 node->key = strdup(key);
65 node->value = strdup(value);
66 if (!node->key || !node->value)
72 freenode(struct envnode *node)
74 free((char *)node->key);
75 free((char *)node->value);
80 addnode(struct env *env, const char *key, const char *value)
84 node = createnode(key, value);
85 RB_INSERT(envtree, &env->root, node);
90 createenv(const struct rule *rule, const struct passwd *mypw,
91 const struct passwd *targpw)
93 static const char *copyset[] = {
100 env = malloc(sizeof(*env));
106 addnode(env, "DOAS_USER", mypw->pw_name);
107 addnode(env, "HOME", targpw->pw_dir);
108 addnode(env, "LOGNAME", targpw->pw_name);
109 addnode(env, "PATH", getenv("PATH"));
110 addnode(env, "SHELL", targpw->pw_shell);
111 addnode(env, "USER", targpw->pw_name);
113 fillenv(env, copyset);
115 if (rule->options & KEEPENV) {
116 extern char **environ;
118 for (i = 0; environ[i] != NULL; i++) {
119 struct envnode *node;
126 /* ignore invalid or overlong names */
127 if ((eq = strchr(e, '=')) == NULL || eq == e)
130 if (len > sizeof(keybuf) - 1)
132 memcpy(keybuf, e, len);
135 node = createnode(keybuf, eq + 1);
136 if (RB_INSERT(envtree, &env->root, node)) {
137 /* ignore any later duplicates */
149 flattenenv(struct env *env)
152 struct envnode *node;
155 envp = reallocarray(NULL, env->count + 1, sizeof(char *));
159 RB_FOREACH(node, envtree, &env->root) {
160 if (asprintf(&envp[i], "%s=%s", node->key, node->value) == -1)
169 fillenv(struct env *env, const char **envlist)
171 struct envnode *node, key;
178 for (i = 0; envlist[i]; i++) {
181 /* parse out env name */
182 if ((eq = strchr(e, '=')) == NULL)
186 if (len > sizeof(name) - 1)
188 memcpy(name, e, len);
191 /* delete previous copies */
195 if ((node = RB_FIND(envtree, &env->root, &key))) {
196 RB_REMOVE(envtree, &env->root, node);
203 /* assign value or inherit from environ */
207 if (strcmp(val + 1, "PATH") == 0)
210 val = getenv(val + 1);
213 if (strcmp(name, "PATH") == 0)
218 /* at last, we have something to insert */
220 node = createnode(name, val);
221 RB_INSERT(envtree, &env->root, node);
228 prepenv(const struct rule *rule, const struct passwd *mypw,
229 const struct passwd *targpw)
233 env = createenv(rule, mypw, targpw);
235 fillenv(env, rule->envlist);
237 return flattenenv(env);