Annotation of src/usr.bin/doas/env.c, Revision 1.7
1.7 ! tedu 1: /* $OpenBSD: env.c,v 1.6 2017/04/06 21:12:06 tedu Exp $ */
1.1 tedu 2: /*
3: * Copyright (c) 2016 Ted Unangst <tedu@openbsd.org>
4: *
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.
8: *
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.
16: */
17:
18: #include <sys/types.h>
1.2 martijn 19: #include <sys/tree.h>
1.1 tedu 20:
21: #include <string.h>
22: #include <stdio.h>
23: #include <stdlib.h>
24: #include <err.h>
25: #include <unistd.h>
26: #include <errno.h>
1.7 ! tedu 27: #include <pwd.h>
1.1 tedu 28:
29: #include "doas.h"
30:
1.2 martijn 31: struct envnode {
32: RB_ENTRY(envnode) node;
33: const char *key;
34: const char *value;
35: };
36:
37: struct env {
38: RB_HEAD(envtree, envnode) root;
39: u_int count;
40: };
41:
1.7 ! tedu 42: static void fillenv(struct env *env, const char **envlist);
! 43:
1.3 tedu 44: static int
1.1 tedu 45: envcmp(struct envnode *a, struct envnode *b)
46: {
47: return strcmp(a->key, b->key);
48: }
1.2 martijn 49: RB_GENERATE_STATIC(envtree, envnode, node, envcmp)
50:
1.3 tedu 51: static struct envnode *
52: createnode(const char *key, const char *value)
53: {
54: struct envnode *node;
1.1 tedu 55:
1.3 tedu 56: node = malloc(sizeof(*node));
57: if (!node)
58: err(1, NULL);
59: node->key = strdup(key);
60: node->value = strdup(value);
61: if (!node->key || !node->value)
62: err(1, NULL);
63: return node;
64: }
65:
66: static void
67: freenode(struct envnode *node)
68: {
69: free((char *)node->key);
70: free((char *)node->value);
71: free(node);
72: }
73:
1.7 ! tedu 74: static void
! 75: addnode(struct env *env, const char *key, const char *value)
! 76: {
! 77: struct envnode *node;
! 78:
! 79: node = createnode(key, value);
! 80: RB_INSERT(envtree, &env->root, node);
! 81: env->count++;
! 82: }
! 83:
1.3 tedu 84: static struct env *
1.7 ! tedu 85: createenv(const struct rule *rule, const struct passwd *mypw,
! 86: const struct passwd *targpw)
1.1 tedu 87: {
88: struct env *env;
89: u_int i;
90:
91: env = malloc(sizeof(*env));
92: if (!env)
93: err(1, NULL);
94: RB_INIT(&env->root);
95: env->count = 0;
96:
1.7 ! tedu 97: addnode(env, "DOAS_USER", mypw->pw_name);
! 98:
1.3 tedu 99: if (rule->options & KEEPENV) {
100: extern const char **environ;
1.1 tedu 101:
1.3 tedu 102: for (i = 0; environ[i] != NULL; i++) {
103: struct envnode *node;
104: const char *e, *eq;
105: size_t len;
1.4 tedu 106: char name[1024];
1.3 tedu 107:
108: e = environ[i];
109:
110: /* ignore invalid or overlong names */
111: if ((eq = strchr(e, '=')) == NULL || eq == e)
112: continue;
113: len = eq - e;
1.4 tedu 114: if (len > sizeof(name) - 1)
1.3 tedu 115: continue;
1.4 tedu 116: memcpy(name, e, len);
117: name[len] = '\0';
1.3 tedu 118:
1.4 tedu 119: node = createnode(name, eq + 1);
1.3 tedu 120: if (RB_INSERT(envtree, &env->root, node)) {
121: /* ignore any later duplicates */
122: freenode(node);
123: } else {
124: env->count++;
125: }
1.1 tedu 126: }
1.7 ! tedu 127: } else {
! 128: static const char *copyset[] = {
! 129: "DISPLAY", "TERM",
! 130: NULL
! 131: };
! 132:
! 133: addnode(env, "HOME", targpw->pw_dir);
! 134: addnode(env, "LOGNAME", targpw->pw_name);
! 135: addnode(env, "PATH", getenv("PATH"));
! 136: addnode(env, "SHELL", targpw->pw_shell);
! 137: addnode(env, "USER", targpw->pw_name);
! 138:
! 139: fillenv(env, copyset);
1.1 tedu 140: }
1.3 tedu 141:
1.1 tedu 142: return env;
143: }
144:
1.3 tedu 145: static char **
1.1 tedu 146: flattenenv(struct env *env)
147: {
148: char **envp;
149: struct envnode *node;
150: u_int i;
151:
152: envp = reallocarray(NULL, env->count + 1, sizeof(char *));
153: if (!envp)
154: err(1, NULL);
155: i = 0;
156: RB_FOREACH(node, envtree, &env->root) {
157: if (asprintf(&envp[i], "%s=%s", node->key, node->value) == -1)
158: err(1, NULL);
159: i++;
160: }
161: envp[i] = NULL;
162: return envp;
163: }
164:
165: static void
1.3 tedu 166: fillenv(struct env *env, const char **envlist)
1.1 tedu 167: {
168: struct envnode *node, key;
1.3 tedu 169: const char *e, *eq;
170: const char *val;
171: char name[1024];
1.1 tedu 172: u_int i;
1.3 tedu 173: size_t len;
1.1 tedu 174:
175: for (i = 0; envlist[i]; i++) {
1.3 tedu 176: e = envlist[i];
177:
178: /* parse out env name */
179: if ((eq = strchr(e, '=')) == NULL)
180: len = strlen(e);
181: else
182: len = eq - e;
183: if (len > sizeof(name) - 1)
184: continue;
185: memcpy(name, e, len);
186: name[len] = '\0';
187:
188: /* delete previous copies */
189: key.key = name;
190: if (*name == '-')
191: key.key = name + 1;
192: if ((node = RB_FIND(envtree, &env->root, &key))) {
193: RB_REMOVE(envtree, &env->root, node);
194: freenode(node);
195: env->count--;
196: }
197: if (*name == '-')
198: continue;
199:
200: /* assign value or inherit from environ */
201: if (eq) {
202: val = eq + 1;
203: if (*val == '$')
204: val = getenv(val + 1);
205: } else {
206: val = getenv(name);
207: }
208: /* at last, we have something to insert */
209: if (val) {
210: node = createnode(name, val);
211: RB_INSERT(envtree, &env->root, node);
212: env->count++;
1.1 tedu 213: }
214: }
215: }
216:
1.3 tedu 217: char **
1.7 ! tedu 218: prepenv(const struct rule *rule, const struct passwd *mypw,
! 219: const struct passwd *targpw)
1.1 tedu 220: {
1.3 tedu 221: struct env *env;
1.5 deraadt 222:
1.7 ! tedu 223: env = createenv(rule, mypw, targpw);
1.1 tedu 224: if (rule->envlist)
1.3 tedu 225: fillenv(env, rule->envlist);
1.2 martijn 226:
227: return flattenenv(env);
1.1 tedu 228: }