Coverage Report

Created: 2025-11-09 06:37

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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
}