]> git.armaanb.net Git - opendoas.git/blob - env.c
the environment handling code was showing its age. just because environ is a char...
[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
20 #include <string.h>
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <err.h>
24 #include <unistd.h>
25 #include <errno.h>
26
27 #include "doas.h"
28
29 int
30 envcmp(struct envnode *a, struct envnode *b)
31 {
32         return strcmp(a->key, b->key);
33 }
34 RB_GENERATE(envtree, envnode, node, envcmp)
35
36 struct env *
37 createenv(char **envp)
38 {
39         struct env *env;
40         u_int i;
41
42         env = malloc(sizeof(*env));
43         if (!env)
44                 err(1, NULL);
45         RB_INIT(&env->root);
46         env->count = 0;
47
48         for (i = 0; envp[i] != NULL; i++) {
49                 struct envnode *node;
50                 const char *e, *eq;
51
52                 e = envp[i];
53
54                 if ((eq = strchr(e, '=')) == NULL || eq == e)
55                         continue;
56                 node = malloc(sizeof(*node));
57                 if (!node)
58                         err(1, NULL);
59                 node->key = strndup(envp[i], eq - e);
60                 node->value = strdup(eq + 1);
61                 if (!node->key || !node->value)
62                         err(1, NULL);
63                 if (RB_FIND(envtree, &env->root, node)) {
64                         free((char *)node->key);
65                         free((char *)node->value);
66                         free(node);
67                 } else {
68                         RB_INSERT(envtree, &env->root, node);
69                         env->count++;
70                 }
71         }
72         return env;
73 }
74
75 char **
76 flattenenv(struct env *env)
77 {
78         char **envp;
79         struct envnode *node;
80         u_int i;
81
82         envp = reallocarray(NULL, env->count + 1, sizeof(char *));
83         if (!envp)
84                 err(1, NULL);
85         i = 0;
86         RB_FOREACH(node, envtree, &env->root) {
87                 if (asprintf(&envp[i], "%s=%s", node->key, node->value) == -1)
88                         err(1, NULL);
89                 i++;
90         }
91         envp[i] = NULL;
92         return envp;
93 }
94
95 static void
96 copyenv(struct env *orig, struct env *copy, const char **envlist)
97 {
98         struct envnode *node, key;
99         u_int i;
100
101         for (i = 0; envlist[i]; i++) {
102                 key.key = envlist[i];
103                 if ((node = RB_FIND(envtree, &orig->root, &key))) {
104                         RB_REMOVE(envtree, &orig->root, node);
105                         orig->count--;
106                         RB_INSERT(envtree, &copy->root, node);
107                         copy->count++;
108                 }
109         }
110 }
111
112 struct env *
113 filterenv(struct env *orig, struct rule *rule)
114 {
115         const char *safeset[] = {
116                 "DISPLAY", "HOME", "LOGNAME", "MAIL",
117                 "PATH", "TERM", "USER", "USERNAME",
118                 NULL
119         };
120         const char *badset[] = {
121                 "ENV",
122                 NULL
123         };
124         struct env *copy;
125         struct envnode *node, key;
126         u_int i;
127
128         if ((rule->options & KEEPENV) && !rule->envlist) {
129                 for (i = 0; badset[i]; i++) {
130                         key.key = badset[i];
131                         if ((node = RB_FIND(envtree, &orig->root, &key))) {
132                                 RB_REMOVE(envtree, &orig->root, node);
133                                 free((char *)node->key);
134                                 free((char *)node->value);
135                                 free(node);
136                                 orig->count--;
137                         }
138                 }
139                 return orig;
140         }
141
142         copy = malloc(sizeof(*copy));
143         if (!copy)
144                 err(1, NULL);
145         RB_INIT(&copy->root);
146         copy->count = 0;
147
148         if (rule->envlist)
149                 copyenv(orig, copy, rule->envlist);
150         copyenv(orig, copy, safeset);
151
152         return copy;
153 }