/src/sudo/plugins/sudoers/sudoers_hooks.c
Line | Count | Source (jump to first uncovered line) |
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 | | /* |
25 | | * This is an open source non-commercial project. Dear PVS-Studio, please check it. |
26 | | * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com |
27 | | */ |
28 | | |
29 | | #include <config.h> |
30 | | |
31 | | #include <stdio.h> |
32 | | #include <stdlib.h> |
33 | | #include <string.h> |
34 | | #include <errno.h> |
35 | | |
36 | | #include "sudoers.h" |
37 | | |
38 | | /* |
39 | | * Similar to setenv(3) but operates on a private copy of the environment. |
40 | | * Does not include warnings or debugging to avoid recursive calls. |
41 | | */ |
42 | | static int |
43 | | sudo_setenv_nodebug(const char *var, const char *val, int overwrite) |
44 | 0 | { |
45 | 0 | char *ep, *estring = NULL; |
46 | 0 | const char *cp; |
47 | 0 | size_t esize; |
48 | 0 | int ret = -1; |
49 | |
|
50 | 0 | if (var == NULL || *var == '\0') { |
51 | 0 | errno = EINVAL; |
52 | 0 | goto done; |
53 | 0 | } |
54 | | |
55 | | /* |
56 | | * POSIX says a var name with '=' is an error but BSD |
57 | | * just ignores the '=' and anything after it. |
58 | | */ |
59 | 0 | for (cp = var; *cp && *cp != '='; cp++) |
60 | 0 | continue; |
61 | 0 | esize = (size_t)(cp - var) + 2; |
62 | 0 | if (val) { |
63 | 0 | esize += strlen(val); /* glibc treats a NULL val as "" */ |
64 | 0 | } |
65 | | |
66 | | /* Allocate and fill in estring. */ |
67 | 0 | if ((estring = ep = malloc(esize)) == NULL) |
68 | 0 | goto done; |
69 | 0 | for (cp = var; *cp && *cp != '='; cp++) |
70 | 0 | *ep++ = *cp; |
71 | 0 | *ep++ = '='; |
72 | 0 | if (val) { |
73 | 0 | for (cp = val; *cp; cp++) |
74 | 0 | *ep++ = *cp; |
75 | 0 | } |
76 | 0 | *ep = '\0'; |
77 | |
|
78 | 0 | ret = sudo_putenv_nodebug(estring, true, overwrite); |
79 | 0 | done: |
80 | 0 | if (ret == -1) |
81 | 0 | free(estring); |
82 | 0 | else |
83 | 0 | sudoers_gc_add(GC_PTR, estring); |
84 | 0 | return ret; |
85 | 0 | } |
86 | | |
87 | | int |
88 | | sudoers_hook_getenv(const char *name, char **value, void *closure) |
89 | 0 | { |
90 | 0 | static bool in_progress = false; /* avoid recursion */ |
91 | |
|
92 | 0 | if (in_progress || env_get() == NULL) |
93 | 0 | return SUDO_HOOK_RET_NEXT; |
94 | | |
95 | 0 | in_progress = true; |
96 | | |
97 | | /* Hack to make GNU gettext() find the sudoers locale when needed. */ |
98 | 0 | if (*name == 'L' && sudoers_getlocale() == SUDOERS_LOCALE_SUDOERS) { |
99 | 0 | if (strcmp(name, "LANGUAGE") == 0 || strcmp(name, "LANG") == 0) { |
100 | 0 | *value = NULL; |
101 | 0 | goto done; |
102 | 0 | } |
103 | 0 | if (strcmp(name, "LC_ALL") == 0 || strcmp(name, "LC_MESSAGES") == 0) { |
104 | 0 | *value = (char *)def_sudoers_locale; |
105 | 0 | goto done; |
106 | 0 | } |
107 | 0 | } |
108 | | |
109 | 0 | *value = sudo_getenv_nodebug(name); |
110 | 0 | done: |
111 | 0 | in_progress = false; |
112 | 0 | return SUDO_HOOK_RET_STOP; |
113 | 0 | } |
114 | | |
115 | | int |
116 | | sudoers_hook_putenv(char *string, void *closure) |
117 | 0 | { |
118 | 0 | static bool in_progress = false; /* avoid recursion */ |
119 | |
|
120 | 0 | if (in_progress || env_get() == NULL) |
121 | 0 | return SUDO_HOOK_RET_NEXT; |
122 | | |
123 | 0 | in_progress = true; |
124 | 0 | sudo_putenv_nodebug(string, true, true); |
125 | 0 | in_progress = false; |
126 | 0 | return SUDO_HOOK_RET_STOP; |
127 | 0 | } |
128 | | |
129 | | int |
130 | | sudoers_hook_setenv(const char *name, const char *value, int overwrite, void *closure) |
131 | 0 | { |
132 | 0 | static bool in_progress = false; /* avoid recursion */ |
133 | |
|
134 | 0 | if (in_progress || env_get() == NULL) |
135 | 0 | return SUDO_HOOK_RET_NEXT; |
136 | | |
137 | 0 | in_progress = true; |
138 | 0 | sudo_setenv_nodebug(name, value, overwrite); |
139 | 0 | in_progress = false; |
140 | 0 | return SUDO_HOOK_RET_STOP; |
141 | 0 | } |
142 | | |
143 | | int |
144 | | sudoers_hook_unsetenv(const char *name, void *closure) |
145 | 0 | { |
146 | 0 | static bool in_progress = false; /* avoid recursion */ |
147 | |
|
148 | 0 | if (in_progress || env_get() == NULL) |
149 | 0 | return SUDO_HOOK_RET_NEXT; |
150 | | |
151 | 0 | in_progress = true; |
152 | 0 | sudo_unsetenv_nodebug(name); |
153 | 0 | in_progress = false; |
154 | 0 | return SUDO_HOOK_RET_STOP; |
155 | 0 | } |