]> git.armaanb.net Git - opendoas.git/blob - env.c
fix sys/tree.h test
[opendoas.git] / env.c
1 /* $OpenBSD$ */
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>
19 #include "sys-tree.h"
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>
27
28 #include "doas.h"
29 #include "includes.h"
30
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
42 int
43 envcmp(struct envnode *a, struct envnode *b)
44 {
45         return strcmp(a->key, b->key);
46 }
47 RB_GENERATE_STATIC(envtree, envnode, node, envcmp)
48
49 struct env *createenv(char **);
50 struct env *filterenv(struct env *, struct rule *);
51 char **flattenenv(struct env *);
52
53 struct env *
54 createenv(char **envp)
55 {
56         struct env *env;
57         u_int i;
58
59         env = malloc(sizeof(*env));
60         if (!env)
61                 err(1, NULL);
62         RB_INIT(&env->root);
63         env->count = 0;
64
65         for (i = 0; envp[i] != NULL; i++) {
66                 struct envnode *node;
67                 const char *e, *eq;
68
69                 e = envp[i];
70
71                 if ((eq = strchr(e, '=')) == NULL || eq == e)
72                         continue;
73                 node = malloc(sizeof(*node));
74                 if (!node)
75                         err(1, NULL);
76                 node->key = strndup(envp[i], eq - e);
77                 node->value = strdup(eq + 1);
78                 if (!node->key || !node->value)
79                         err(1, NULL);
80                 if (RB_FIND(envtree, &env->root, node)) {
81                         free((char *)node->key);
82                         free((char *)node->value);
83                         free(node);
84                 } else {
85                         RB_INSERT(envtree, &env->root, node);
86                         env->count++;
87                 }
88         }
89         return env;
90 }
91
92 char **
93 flattenenv(struct env *env)
94 {
95         char **envp;
96         struct envnode *node;
97         u_int i;
98
99         envp = reallocarray(NULL, env->count + 1, sizeof(char *));
100         if (!envp)
101                 err(1, NULL);
102         i = 0;
103         RB_FOREACH(node, envtree, &env->root) {
104                 if (asprintf(&envp[i], "%s=%s", node->key, node->value) == -1)
105                         err(1, NULL);
106                 i++;
107         }
108         envp[i] = NULL;
109         return envp;
110 }
111
112 static void
113 copyenv(struct env *orig, struct env *copy, const char **envlist)
114 {
115         struct envnode *node, key;
116         u_int i;
117
118         for (i = 0; envlist[i]; i++) {
119                 key.key = envlist[i];
120                 if ((node = RB_FIND(envtree, &orig->root, &key))) {
121                         RB_REMOVE(envtree, &orig->root, node);
122                         orig->count--;
123                         RB_INSERT(envtree, &copy->root, node);
124                         copy->count++;
125                 }
126         }
127 }
128
129 struct env *
130 filterenv(struct env *orig, struct rule *rule)
131 {
132         const char *safeset[] = {
133                 "DISPLAY", "HOME", "LOGNAME", "MAIL",
134                 "PATH", "TERM", "USER", "USERNAME",
135                 NULL
136         };
137         const char *badset[] = {
138                 "ENV",
139                 NULL
140         };
141         struct env *copy;
142         struct envnode *node, key;
143         u_int i;
144
145         if ((rule->options & KEEPENV) && !rule->envlist) {
146                 for (i = 0; badset[i]; i++) {
147                         key.key = badset[i];
148                         if ((node = RB_FIND(envtree, &orig->root, &key))) {
149                                 RB_REMOVE(envtree, &orig->root, node);
150                                 free((char *)node->key);
151                                 free((char *)node->value);
152                                 free(node);
153                                 orig->count--;
154                         }
155                 }
156                 return orig;
157         }
158
159         copy = malloc(sizeof(*copy));
160         if (!copy)
161                 err(1, NULL);
162         RB_INIT(&copy->root);
163         copy->count = 0;
164
165         if (rule->envlist)
166                 copyenv(orig, copy, rule->envlist);
167         copyenv(orig, copy, safeset);
168
169         return copy;
170 }
171
172 char **
173 prepenv(struct rule *rule)
174 {
175         extern char **environ;
176         struct env *env;
177         
178         env = createenv(environ);
179         env = filterenv(env, rule);
180         return flattenenv(env);
181 }