Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/tools/regression/security/access/testaccess.c
48266 views
1
/*-
2
* Copyright (c) 2001 Networks Associates Technology, Inc.
3
* All rights reserved.
4
*
5
* Redistribution and use in source and binary forms, with or without
6
* modification, are permitted provided that the following conditions
7
* are met:
8
* 1. Redistributions of source code must retain the above copyright
9
* notice, this list of conditions and the following disclaimer.
10
* 2. Redistributions in binary form must reproduce the above copyright
11
* notice, this list of conditions and the following disclaimer in the
12
* documentation and/or other materials provided with the distribution.
13
*
14
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24
* SUCH DAMAGE.
25
*
26
* Written at NAI Labs at Network Associates by Robert Watson for the
27
* TrustedBSD Project.
28
*
29
* Work sponsored by Defense Advanced Research Projects Agency under the
30
* CHATS research program, CBOSS project.
31
*/
32
33
#include <sys/types.h>
34
35
#include <errno.h>
36
#include <fcntl.h>
37
#include <stdio.h>
38
#include <stdlib.h>
39
#include <unistd.h>
40
41
/*
42
* Regression test to check some basic cases and see if access() and
43
* eaccess() are using the correct portions of the process credential.
44
* This test relies on running with privilege, and on UFS filesystem
45
* semantics. Running the test in other environments may result
46
* in incorrect failure identification.
47
*
48
* Note that this may also break if filesystem access control is
49
* broken, or if the ability to check and set credentials is broken.
50
*
51
* Note that this test uses two hard-coded non-root UIDs; on multi-user
52
* systems, these UIDs may be in use by an untrusted user, in which
53
* case those users could interfere with the test.
54
*/
55
56
#define ROOT_UID (uid_t)0
57
#define WHEEL_GID (gid_t)0
58
#define TEST_UID_ONE (uid_t)500
59
#define TEST_GID_ONE (gid_t)500
60
#define TEST_UID_TWO (uid_t)501
61
#define TEST_GID_TWO (gid_t)501
62
63
struct file_description {
64
char *fd_name;
65
uid_t fd_owner;
66
gid_t fd_group;
67
mode_t fd_mode;
68
};
69
70
static struct file_description fd_list[] = {
71
{"test1", ROOT_UID, WHEEL_GID, 0400},
72
{"test2", TEST_UID_ONE, WHEEL_GID,0400},
73
{"test3", TEST_UID_TWO, WHEEL_GID, 0400},
74
{"test4", ROOT_UID, WHEEL_GID, 0040},
75
{"test5", ROOT_UID, TEST_GID_ONE, 0040},
76
{"test6", ROOT_UID, TEST_GID_TWO, 0040}};
77
78
static int fd_list_count = sizeof(fd_list) /
79
sizeof(struct file_description);
80
81
int
82
setup(void)
83
{
84
int i, error;
85
86
for (i = 0; i < fd_list_count; i++) {
87
error = open(fd_list[i].fd_name, O_CREAT | O_EXCL, fd_list[i].fd_mode);
88
if (error == -1) {
89
perror("open");
90
return (error);
91
}
92
close(error);
93
error = chown(fd_list[i].fd_name, fd_list[i].fd_owner,
94
fd_list[i].fd_group);
95
if (error) {
96
perror("chown");
97
return (error);
98
}
99
}
100
return (0);
101
}
102
103
int
104
restoreprivilege(void)
105
{
106
int error;
107
108
error = setreuid(ROOT_UID, ROOT_UID);
109
if (error)
110
return (error);
111
112
error = setregid(WHEEL_GID, WHEEL_GID);
113
if (error)
114
return (error);
115
116
return (0);
117
}
118
119
int
120
reportprivilege(char *message)
121
{
122
uid_t euid, ruid, suid;
123
gid_t egid, rgid, sgid;
124
int error;
125
126
error = getresuid(&ruid, &euid, &suid);
127
if (error) {
128
perror("getresuid");
129
return (error);
130
}
131
132
error = getresgid(&rgid, &egid, &sgid);
133
if (error) {
134
perror("getresgid");
135
return (error);
136
}
137
138
if (message)
139
printf("%s: ", message);
140
printf("ruid: %d, euid: %d, suid: %d, ", ruid, euid, suid);
141
printf("rgid: %d, egid: %d, sgid: %d\n", rgid, egid, sgid);
142
143
return (0);
144
}
145
146
int
147
cleanup(void)
148
{
149
int i, error;
150
151
error = restoreprivilege();
152
if (error) {
153
perror("restoreprivilege");
154
return (error);
155
}
156
157
for (i = 0; i < fd_list_count; i++) {
158
error = unlink(fd_list[i].fd_name);
159
if (error)
160
return (error);
161
}
162
163
return (0);
164
}
165
166
int
167
main(int argc, char *argv[])
168
{
169
int error, errorseen;
170
171
if (geteuid() != 0) {
172
fprintf(stderr, "testaccess must run as root.\n");
173
exit (EXIT_FAILURE);
174
}
175
176
error = setup();
177
if (error) {
178
cleanup();
179
exit (EXIT_FAILURE);
180
}
181
182
/* Make sure saved uid is set appropriately. */
183
error = setresuid(ROOT_UID, ROOT_UID, ROOT_UID);
184
if (error) {
185
perror("setresuid");
186
cleanup();
187
}
188
189
/* Clear out additional groups. */
190
error = setgroups(0, NULL);
191
if (error) {
192
perror("setgroups");
193
cleanup();
194
}
195
196
/* Make sure saved gid is set appropriately. */
197
error = setresgid(WHEEL_GID, WHEEL_GID, WHEEL_GID);
198
if (error) {
199
perror("setresgid");
200
cleanup();
201
}
202
203
/*
204
* UID-only tests.
205
*/
206
207
/* Check that saved uid is not used */
208
error = setresuid(TEST_UID_ONE, TEST_UID_ONE, ROOT_UID);
209
if (error) {
210
perror("setresuid.1");
211
cleanup();
212
exit (EXIT_FAILURE);
213
}
214
215
errorseen = 0;
216
217
error = access("test1", R_OK);
218
if (!error) {
219
fprintf(stderr, "saved uid used instead of real uid\n");
220
errorseen++;
221
}
222
223
#ifdef EACCESS_AVAILABLE
224
error = eaccess("test1", R_OK);
225
if (!error) {
226
fprintf(stderr, "saved uid used instead of effective uid\n");
227
errorseen++;
228
}
229
#endif
230
231
error = restoreprivilege();
232
if (error) {
233
perror("restoreprivilege");
234
cleanup();
235
exit (EXIT_FAILURE);
236
}
237
238
error = setresuid(TEST_UID_ONE, TEST_UID_TWO, ROOT_UID);
239
if (error) {
240
perror("setresid.2");
241
cleanup();
242
exit (EXIT_FAILURE);
243
}
244
245
/* Check that the real uid is used, not the effective uid */
246
error = access("test2", R_OK);
247
if (error) {
248
fprintf(stderr, "Effective uid was used instead of real uid in access().\n");
249
errorseen++;
250
}
251
252
#ifdef EACCESS_AVAILABLE
253
/* Check that the effective uid is used, not the real uid */
254
error = eaccess("test3", R_OK);
255
if (error) {
256
fprintf(stderr, "Real uid was used instead of effective uid in eaccess().\n");
257
errorseen++;
258
}
259
#endif
260
261
/* Check that the real uid is used, not the effective uid */
262
error = access("test3", R_OK);
263
if (!error) {
264
fprintf(stderr, "Effective uid was used instead of real uid in access().\n");
265
errorseen++;
266
}
267
268
#ifdef EACCESS_AVAILABLE
269
/* Check that the effective uid is used, not the real uid */
270
error = eaccess("test2", R_OK);
271
if (!error) {
272
fprintf(stderr, "Real uid was used instead of effective uid in eaccess().\n");
273
errorseen++;
274
}
275
#endif
276
277
error = restoreprivilege();
278
if (error) {
279
perror("restoreprivilege");
280
cleanup();
281
exit (EXIT_FAILURE);
282
}
283
284
error = setresgid(TEST_GID_ONE, TEST_GID_TWO, WHEEL_GID);
285
if (error) {
286
perror("setresgid.1");
287
cleanup();
288
exit (EXIT_FAILURE);
289
}
290
291
/* Set non-root effective uid to avoid excess privilege. */
292
error = setresuid(TEST_UID_ONE, TEST_UID_ONE, ROOT_UID);
293
if (error) {
294
perror("setresuid.3");
295
cleanup();
296
exit (EXIT_FAILURE);
297
}
298
299
/* Check that the saved gid is not used */
300
error = access("test4", R_OK);
301
if (!error) {
302
fprintf(stderr, "saved gid used instead of real gid\n");
303
}
304
305
#ifdef EACCESS_AVAILABLE
306
error = eaccess("test4", R_OK);
307
if (!error) {
308
fprintf(stderr, "saved gid used instead of effective gid\n");
309
errorseen++;
310
}
311
#endif
312
313
/* Check that the real gid is used, not the effective gid */
314
error = access("test5", R_OK);
315
if (error) {
316
fprintf(stderr, "Effective gid was used instead of real gid in access().\n");
317
errorseen++;
318
}
319
320
#ifdef EACCESS_AVAILABLE
321
/* Check that the effective gid is used, not the real gid */
322
error = eaccess("test6", R_OK);
323
if (error) {
324
fprintf(stderr, "Real gid was used instead of effective gid in eaccess().\n");
325
errorseen++;
326
}
327
#endif
328
329
/* Check that the real gid is used, not the effective gid */
330
error = access("test6", R_OK);
331
if (!error) {
332
fprintf(stderr, "Effective gid was used instead of real gid in access().\n");
333
errorseen++;
334
}
335
336
#ifdef EACCESS_AVAILABLE
337
/* Check that the effective gid is used, not the real gid */
338
error = eaccess("test5", R_OK);
339
if (!error) {
340
fprintf(stderr, "Real gid was used instead of effective gid in eaccess().\n");
341
errorseen++;
342
}
343
#endif
344
345
fprintf(stderr, "%d errors seen.\n", errorseen);
346
347
/*
348
* All tests done, restore and clean up
349
*/
350
351
error = cleanup();
352
if (error) {
353
perror("cleanup");
354
exit (EXIT_FAILURE);
355
}
356
357
exit (EXIT_SUCCESS);
358
}
359
360