Annotation of embedaddon/sudo/src/env_hooks.c, revision 1.1.1.3
1.1 misho 1: /*
2: * Copyright (c) 2010, 2012 Todd C. Miller <Todd.Miller@courtesan.com>
3: *
4: * Permission to use, copy, modify, and distribute this software for any
5: * purpose with or without fee is hereby granted, provided that the above
6: * copyright notice and this permission notice appear in all copies.
7: *
8: * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9: * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10: * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11: * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12: * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13: * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14: * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15: */
16:
17: #include <config.h>
18:
19: #include <sys/types.h>
20:
21: #include <stdio.h>
22: #ifdef STDC_HEADERS
23: # include <stdlib.h>
24: # include <stddef.h>
25: #else
26: # ifdef HAVE_STDLIB_H
27: # include <stdlib.h>
28: # endif
29: #endif /* STDC_HEADERS */
30: #ifdef HAVE_STRING_H
31: # include <string.h>
32: #endif /* HAVE_STRING_H */
33: #ifdef HAVE_STRINGS_H
34: # include <strings.h>
35: #endif /* HAVE_STRINGS_H */
36: #if defined(HAVE_MALLOC_H) && !defined(STDC_HEADERS)
37: # include <malloc.h>
38: #endif /* HAVE_MALLOC_H && !STDC_HEADERS */
39: #include <errno.h>
40:
41: #include "sudo.h"
42: #include "sudo_plugin.h"
1.1.1.3 ! misho 43: #include "sudo_dso.h"
1.1 misho 44:
45: extern char **environ; /* global environment pointer */
46: static char **priv_environ; /* private environment pointer */
47:
48: static char *
49: rpl_getenv(const char *name)
50: {
51: char **ep, *val = NULL;
52: size_t namelen = 0;
53:
54: /* For BSD compatibility, treat '=' in name like end of string. */
55: while (name[namelen] != '\0' && name[namelen] != '=')
56: namelen++;
57: for (ep = environ; *ep != NULL; ep++) {
58: if (strncmp(*ep, name, namelen) == 0 && (*ep)[namelen] == '=') {
59: val = *ep + namelen + 1;
60: break;
61: }
62: }
63: return val;
64: }
65:
66: typedef char * (*sudo_fn_getenv_t)(const char *);
67:
68: char *
1.1.1.2 misho 69: getenv_unhooked(const char *name)
70: {
71: sudo_fn_getenv_t fn;
72:
1.1.1.3 ! misho 73: fn = (sudo_fn_getenv_t)sudo_dso_findsym(SUDO_DSO_NEXT, "getenv");
1.1.1.2 misho 74: if (fn != NULL)
75: return fn(name);
76: return rpl_getenv(name);
77: }
78:
1.1.1.3 ! misho 79: __dso_public char *getenv(const char *);
! 80:
1.1.1.2 misho 81: char *
1.1 misho 82: getenv(const char *name)
83: {
84: char *val = NULL;
85:
86: switch (process_hooks_getenv(name, &val)) {
87: case SUDO_HOOK_RET_STOP:
88: return val;
89: case SUDO_HOOK_RET_ERROR:
90: return NULL;
1.1.1.2 misho 91: default:
92: return getenv_unhooked(name);
1.1 misho 93: }
94: }
95:
96: static int
97: rpl_putenv(PUTENV_CONST char *string)
98: {
99: char **ep;
100: size_t len;
101: bool found = false;
102:
103: /* Look for existing entry. */
104: len = (strchr(string, '=') - string) + 1;
105: for (ep = environ; *ep != NULL; ep++) {
106: if (strncmp(string, *ep, len) == 0) {
107: *ep = (char *)string;
108: found = true;
109: break;
110: }
111: }
112: /* Prune out duplicate variables. */
113: if (found) {
114: while (*ep != NULL) {
115: if (strncmp(string, *ep, len) == 0) {
116: char **cur = ep;
117: while ((*cur = *(cur + 1)) != NULL)
118: cur++;
119: } else {
120: ep++;
121: }
122: }
123: }
124:
125: /* Append at the end if not already found. */
126: if (!found) {
127: size_t env_len = (size_t)(ep - environ);
128: char **envp = erealloc3(priv_environ, env_len + 2, sizeof(char *));
129: if (environ != priv_environ)
130: memcpy(envp, environ, env_len * sizeof(char *));
131: envp[env_len++] = (char *)string;
132: envp[env_len] = NULL;
133: priv_environ = environ = envp;
134: }
135: return 0;
136: }
137:
138: typedef int (*sudo_fn_putenv_t)(PUTENV_CONST char *);
139:
1.1.1.2 misho 140: static int
141: putenv_unhooked(PUTENV_CONST char *string)
142: {
143: sudo_fn_putenv_t fn;
144:
1.1.1.3 ! misho 145: fn = (sudo_fn_putenv_t)sudo_dso_findsym(SUDO_DSO_NEXT, "putenv");
1.1.1.2 misho 146: if (fn != NULL)
147: return fn(string);
148: return rpl_putenv(string);
149: }
150:
1.1 misho 151: int
152: putenv(PUTENV_CONST char *string)
153: {
154: switch (process_hooks_putenv((char *)string)) {
155: case SUDO_HOOK_RET_STOP:
156: return 0;
157: case SUDO_HOOK_RET_ERROR:
158: return -1;
1.1.1.2 misho 159: default:
160: return putenv_unhooked(string);
1.1 misho 161: }
162: }
163:
164: static int
165: rpl_setenv(const char *var, const char *val, int overwrite)
166: {
167: char *envstr, *dst;
168: const char *src;
169: size_t esize;
170:
171: if (!var || *var == '\0') {
172: errno = EINVAL;
173: return -1;
174: }
175:
176: /*
177: * POSIX says a var name with '=' is an error but BSD
178: * just ignores the '=' and anything after it.
179: */
180: for (src = var; *src != '\0' && *src != '='; src++)
181: ;
182: esize = (size_t)(src - var) + 2;
183: if (val) {
184: esize += strlen(val); /* glibc treats a NULL val as "" */
185: }
186:
187: /* Allocate and fill in envstr. */
188: if ((envstr = malloc(esize)) == NULL)
189: return -1;
190: for (src = var, dst = envstr; *src != '\0' && *src != '=';)
191: *dst++ = *src++;
192: *dst++ = '=';
193: if (val) {
194: for (src = val; *src != '\0';)
195: *dst++ = *src++;
196: }
197: *dst = '\0';
198:
199: if (!overwrite && getenv(var) != NULL) {
200: free(envstr);
201: return 0;
202: }
203: return rpl_putenv(envstr);
204: }
205:
206: typedef int (*sudo_fn_setenv_t)(const char *, const char *, int);
207:
1.1.1.2 misho 208: static int
209: setenv_unhooked(const char *var, const char *val, int overwrite)
210: {
211: sudo_fn_setenv_t fn;
212:
1.1.1.3 ! misho 213: fn = (sudo_fn_setenv_t)sudo_dso_findsym(SUDO_DSO_NEXT, "setenv");
1.1.1.2 misho 214: if (fn != NULL)
215: return fn(var, val, overwrite);
216: return rpl_setenv(var, val, overwrite);
217: }
218:
1.1 misho 219: int
220: setenv(const char *var, const char *val, int overwrite)
221: {
222: switch (process_hooks_setenv(var, val, overwrite)) {
223: case SUDO_HOOK_RET_STOP:
224: return 0;
225: case SUDO_HOOK_RET_ERROR:
226: return -1;
1.1.1.2 misho 227: default:
228: return setenv_unhooked(var, val, overwrite);
1.1 misho 229: }
230: }
231:
1.1.1.2 misho 232: static int
1.1 misho 233: rpl_unsetenv(const char *var)
234: {
235: char **ep = environ;
236: size_t len;
237:
238: if (var == NULL || *var == '\0' || strchr(var, '=') != NULL) {
239: errno = EINVAL;
240: return -1;
241: }
242:
243: len = strlen(var);
244: while (*ep != NULL) {
245: if (strncmp(var, *ep, len) == 0 && (*ep)[len] == '=') {
246: /* Found it; shift remainder + NULL over by one. */
247: char **cur = ep;
248: while ((*cur = *(cur + 1)) != NULL)
249: cur++;
250: /* Keep going, could be multiple instances of the var. */
251: } else {
252: ep++;
253: }
254: }
255: return 0;
256: }
257:
258: #ifdef UNSETENV_VOID
259: typedef void (*sudo_fn_unsetenv_t)(const char *);
260: #else
261: typedef int (*sudo_fn_unsetenv_t)(const char *);
262: #endif
263:
1.1.1.2 misho 264: static int
265: unsetenv_unhooked(const char *var)
1.1 misho 266: {
1.1.1.2 misho 267: int rval = 0;
268: sudo_fn_unsetenv_t fn;
1.1 misho 269:
1.1.1.3 ! misho 270: fn = (sudo_fn_unsetenv_t)sudo_dso_findsym(SUDO_DSO_NEXT, "unsetenv");
1.1.1.2 misho 271: if (fn != NULL) {
272: # ifdef UNSETENV_VOID
273: fn(var);
274: # else
275: rval = fn(var);
276: # endif
1.1.1.3 ! misho 277: } else {
1.1.1.2 misho 278: rval = rpl_unsetenv(var);
1.1 misho 279: }
1.1.1.2 misho 280: return rval;
1.1 misho 281: }
1.1.1.2 misho 282:
283: #ifdef UNSETENV_VOID
284: void
1.1 misho 285: #else
286: int
1.1.1.2 misho 287: #endif
1.1 misho 288: unsetenv(const char *var)
289: {
1.1.1.2 misho 290: int rval;
291:
1.1 misho 292: switch (process_hooks_unsetenv(var)) {
293: case SUDO_HOOK_RET_STOP:
1.1.1.2 misho 294: rval = 0;
295: break;
1.1 misho 296: case SUDO_HOOK_RET_ERROR:
1.1.1.2 misho 297: rval = -1;
298: break;
299: default:
300: rval = unsetenv_unhooked(var);
301: break;
1.1 misho 302: }
1.1.1.2 misho 303: #ifndef UNSETENV_VOID
304: return rval;
305: #endif
1.1 misho 306: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>