/src/sudo/plugins/sudoers/sudoers_hooks.c
Line | Count | Source |
1 | | /* |
2 | | * SPDX-License-Identifier: ISC |
3 | | * |
4 | | * Copyright (c) 2000-2005, 2007-2019 |
5 | | * Todd C. Miller <Todd.Miller@sudo.ws> |
6 | | * |
7 | | * Permission to use, copy, modify, and distribute this software for any |
8 | | * purpose with or without fee is hereby granted, provided that the above |
9 | | * copyright notice and this permission notice appear in all copies. |
10 | | * |
11 | | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
12 | | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
13 | | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR |
14 | | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
15 | | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN |
16 | | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF |
17 | | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
18 | | * |
19 | | * Sponsored in part by the Defense Advanced Research Projects |
20 | | * Agency (DARPA) and Air Force Research Laboratory, Air Force |
21 | | * Materiel Command, USAF, under agreement number F39502-99-1-0512. |
22 | | */ |
23 | | |
24 | | #include <config.h> |
25 | | |
26 | | #include <stdio.h> |
27 | | #include <stdlib.h> |
28 | | #include <string.h> |
29 | | #include <errno.h> |
30 | | |
31 | | #include <sudoers.h> |
32 | | |
33 | | /* |
34 | | * Similar to setenv(3) but operates on a private copy of the environment. |
35 | | * Does not include warnings or debugging to avoid recursive calls. |
36 | | */ |
37 | | static int |
38 | | sudo_setenv_nodebug(const char *var, const char *val, int overwrite) |
39 | 0 | { |
40 | 0 | char *ep, *estring = NULL; |
41 | 0 | const char *cp; |
42 | 0 | size_t esize; |
43 | 0 | int ret = -1; |
44 | |
|
45 | 0 | if (var == NULL || *var == '\0') { |
46 | 0 | errno = EINVAL; |
47 | 0 | goto done; |
48 | 0 | } |
49 | | |
50 | | /* |
51 | | * POSIX says a var name with '=' is an error but BSD |
52 | | * just ignores the '=' and anything after it. |
53 | | */ |
54 | 0 | for (cp = var; *cp && *cp != '='; cp++) |
55 | 0 | continue; |
56 | 0 | esize = (size_t)(cp - var) + 2; |
57 | 0 | if (val) { |
58 | 0 | esize += strlen(val); /* glibc treats a NULL val as "" */ |
59 | 0 | } |
60 | | |
61 | | /* Allocate and fill in estring. */ |
62 | 0 | if ((estring = ep = malloc(esize)) == NULL) |
63 | 0 | goto done; |
64 | 0 | for (cp = var; *cp && *cp != '='; cp++) |
65 | 0 | *ep++ = *cp; |
66 | 0 | *ep++ = '='; |
67 | 0 | if (val) { |
68 | 0 | for (cp = val; *cp; cp++) |
69 | 0 | *ep++ = *cp; |
70 | 0 | } |
71 | 0 | *ep = '\0'; |
72 | |
|
73 | 0 | ret = sudo_putenv_nodebug(estring, true, overwrite); |
74 | 0 | done: |
75 | 0 | if (ret == -1) |
76 | 0 | free(estring); |
77 | 0 | else |
78 | 0 | sudoers_gc_add(GC_PTR, estring); |
79 | 0 | return ret; |
80 | 0 | } |
81 | | |
82 | | int |
83 | | sudoers_hook_getenv(const char *name, char **value, void *closure) |
84 | 0 | { |
85 | 0 | static bool in_progress = false; /* avoid recursion */ |
86 | |
|
87 | 0 | if (in_progress || env_get() == NULL) |
88 | 0 | return SUDO_HOOK_RET_NEXT; |
89 | | |
90 | 0 | in_progress = true; |
91 | | |
92 | | /* Hack to make GNU gettext() find the sudoers locale when needed. */ |
93 | 0 | if (*name == 'L' && sudoers_getlocale() == SUDOERS_LOCALE_SUDOERS) { |
94 | 0 | if (strcmp(name, "LANGUAGE") == 0 || strcmp(name, "LANG") == 0) { |
95 | 0 | *value = NULL; |
96 | 0 | goto done; |
97 | 0 | } |
98 | 0 | if (strcmp(name, "LC_ALL") == 0 || strcmp(name, "LC_MESSAGES") == 0) { |
99 | 0 | *value = def_sudoers_locale; |
100 | 0 | goto done; |
101 | 0 | } |
102 | 0 | } |
103 | | |
104 | 0 | *value = sudo_getenv_nodebug(name); |
105 | 0 | done: |
106 | 0 | in_progress = false; |
107 | 0 | return SUDO_HOOK_RET_STOP; |
108 | 0 | } |
109 | | |
110 | | int |
111 | | sudoers_hook_putenv(char *string, void *closure) |
112 | 0 | { |
113 | 0 | static bool in_progress = false; /* avoid recursion */ |
114 | |
|
115 | 0 | if (in_progress || env_get() == NULL) |
116 | 0 | return SUDO_HOOK_RET_NEXT; |
117 | | |
118 | 0 | in_progress = true; |
119 | 0 | sudo_putenv_nodebug(string, true, true); |
120 | 0 | in_progress = false; |
121 | 0 | return SUDO_HOOK_RET_STOP; |
122 | 0 | } |
123 | | |
124 | | int |
125 | | sudoers_hook_setenv(const char *name, const char *value, int overwrite, void *closure) |
126 | 0 | { |
127 | 0 | static bool in_progress = false; /* avoid recursion */ |
128 | |
|
129 | 0 | if (in_progress || env_get() == NULL) |
130 | 0 | return SUDO_HOOK_RET_NEXT; |
131 | | |
132 | 0 | in_progress = true; |
133 | 0 | sudo_setenv_nodebug(name, value, overwrite); |
134 | 0 | in_progress = false; |
135 | 0 | return SUDO_HOOK_RET_STOP; |
136 | 0 | } |
137 | | |
138 | | int |
139 | | sudoers_hook_unsetenv(const char *name, void *closure) |
140 | 0 | { |
141 | 0 | static bool in_progress = false; /* avoid recursion */ |
142 | |
|
143 | 0 | if (in_progress || env_get() == NULL) |
144 | 0 | return SUDO_HOOK_RET_NEXT; |
145 | | |
146 | 0 | in_progress = true; |
147 | 0 | sudo_unsetenv_nodebug(name); |
148 | 0 | in_progress = false; |
149 | 0 | return SUDO_HOOK_RET_STOP; |
150 | 0 | } |