Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sudo-project
GitHub Repository: sudo-project/sudo
Path: blob/main/lib/util/getusershell.c
1532 views
1
/*
2
* SPDX-License-Identifier: ISC
3
*
4
* Copyright (c) 2019-2020 Todd C. Miller <[email protected]>
5
*
6
* Permission to use, copy, modify, and distribute this software for any
7
* purpose with or without fee is hereby granted, provided that the above
8
* copyright notice and this permission notice appear in all copies.
9
*
10
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17
*/
18
19
#include <config.h>
20
21
#include <stdio.h>
22
#include <stdlib.h>
23
#include <string.h>
24
25
#include <sudo_compat.h>
26
#include <sudo_debug.h>
27
#include <sudo_util.h>
28
29
#ifdef TESTSUDOERS
30
# include <tsgetgrpw.h>
31
#endif
32
33
static const char *shellfile = "/etc/shell";
34
static char **allowed_shells, * const *current_shell;
35
static const char *default_shells[] = {
36
"/bin/sh",
37
"/bin/ksh",
38
"/bin/ksh93",
39
"/bin/bash",
40
"/bin/dash",
41
"/bin/zsh",
42
"/bin/csh",
43
"/bin/tcsh",
44
NULL
45
};
46
47
static char **
48
read_shells(void)
49
{
50
size_t maxshells = 16, nshells = 0;
51
size_t linesize = 0;
52
char *line = NULL;
53
FILE *fp;
54
debug_decl(read_shells, SUDO_DEBUG_UTIL);
55
56
if ((fp = fopen(shellfile, "r")) == NULL)
57
goto bad;
58
59
free(allowed_shells);
60
allowed_shells = reallocarray(NULL, maxshells, sizeof(char *));
61
if (allowed_shells == NULL)
62
goto bad;
63
64
while (sudo_parseln(&line, &linesize, NULL, fp, PARSELN_CONT_IGN) != -1) {
65
if (nshells + 1 >= maxshells) {
66
char **new_shells;
67
68
new_shells = reallocarray(NULL, maxshells + 16, sizeof(char *));
69
if (new_shells == NULL)
70
goto bad;
71
allowed_shells = new_shells;
72
maxshells += 16;
73
}
74
if ((allowed_shells[nshells] = strdup(line)) == NULL)
75
goto bad;
76
nshells++;
77
}
78
allowed_shells[nshells] = NULL;
79
80
free(line);
81
fclose(fp);
82
debug_return_ptr(allowed_shells);
83
bad:
84
free(line);
85
if (fp != NULL)
86
fclose(fp);
87
while (nshells != 0)
88
free(allowed_shells[--nshells]);
89
free(allowed_shells);
90
allowed_shells = NULL;
91
debug_return_ptr(default_shells);
92
}
93
94
void
95
sudo_setusershell(void)
96
{
97
debug_decl(setusershell, SUDO_DEBUG_UTIL);
98
99
current_shell = read_shells();
100
101
debug_return;
102
}
103
104
void
105
sudo_endusershell(void)
106
{
107
debug_decl(endusershell, SUDO_DEBUG_UTIL);
108
109
if (allowed_shells != NULL) {
110
char **shell;
111
112
for (shell = allowed_shells; *shell != NULL; shell++)
113
free(*shell);
114
free(allowed_shells);
115
allowed_shells = NULL;
116
}
117
current_shell = NULL;
118
119
debug_return;
120
}
121
122
char *
123
sudo_getusershell(void)
124
{
125
debug_decl(getusershell, SUDO_DEBUG_UTIL);
126
127
if (current_shell == NULL)
128
current_shell = read_shells();
129
130
debug_return_str(*current_shell++);
131
}
132
133
#ifdef TESTSUDOERS
134
void
135
testsudoers_setshellfile(const char *file)
136
{
137
testsudoers_endusershell();
138
shellfile = file;
139
}
140
#endif /* TESTSUDOERS */
141
142