2 * Copyright (c) 2001 Networks Associates Technology, Inc.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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.
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
26 * Written at NAI Labs at Network Associates by Robert Watson for the
29 * Work sponsored by Defense Advanced Research Projects Agency under the
30 * CHATS research program, CBOSS project.
35 #include <sys/types.h>
44 * Regression test to check some basic cases and see if access() and
45 * eaccess() are using the correct portions of the process credential.
46 * This test relies on running with privilege, and on UFS filesystem
47 * semantics. Running the test in other environments may result
48 * in incorrect failure identification.
50 * Note that this may also break if filesystem access control is
51 * broken, or if the ability to check and set credentials is broken.
53 * Note that this test uses two hard-coded non-root UIDs; on multi-user
54 * systems, these UIDs may be in use by an untrusted user, in which
55 * case those users could interfere with the test.
58 #define ROOT_UID (uid_t)0
59 #define WHEEL_GID (gid_t)0
60 #define TEST_UID_ONE (uid_t)500
61 #define TEST_GID_ONE (gid_t)500
62 #define TEST_UID_TWO (uid_t)501
63 #define TEST_GID_TWO (gid_t)501
65 struct file_description {
72 static struct file_description fd_list[] = {
73 {"test1", ROOT_UID, WHEEL_GID, 0400},
74 {"test2", TEST_UID_ONE, WHEEL_GID,0400},
75 {"test3", TEST_UID_TWO, WHEEL_GID, 0400},
76 {"test4", ROOT_UID, WHEEL_GID, 0040},
77 {"test5", ROOT_UID, TEST_GID_ONE, 0040},
78 {"test6", ROOT_UID, TEST_GID_TWO, 0040}};
80 static int fd_list_count = sizeof(fd_list) /
81 sizeof(struct file_description);
88 for (i = 0; i < fd_list_count; i++) {
89 error = open(fd_list[i].fd_name, O_CREAT | O_EXCL, fd_list[i].fd_mode);
95 error = chown(fd_list[i].fd_name, fd_list[i].fd_owner,
106 restoreprivilege(void)
110 error = setreuid(ROOT_UID, ROOT_UID);
114 error = setregid(WHEEL_GID, WHEEL_GID);
122 reportprivilege(char *message)
124 uid_t euid, ruid, suid;
125 gid_t egid, rgid, sgid;
128 error = getresuid(&ruid, &euid, &suid);
134 error = getresgid(&rgid, &egid, &sgid);
141 printf("%s: ", message);
142 printf("ruid: %d, euid: %d, suid: %d, ", ruid, euid, suid);
143 printf("rgid: %d, egid: %d, sgid: %d\n", rgid, egid, sgid);
153 error = restoreprivilege();
155 perror("restoreprivilege");
159 for (i = 0; i < fd_list_count; i++) {
160 error = unlink(fd_list[i].fd_name);
169 main(int argc, char *argv[])
171 int error, errorseen;
173 if (geteuid() != 0) {
174 fprintf(stderr, "testaccess must run as root.\n");
184 /* Make sure saved uid is set appropriately. */
185 error = setresuid(ROOT_UID, ROOT_UID, ROOT_UID);
191 /* Clear out additional groups. */
192 error = setgroups(0, NULL);
198 /* Make sure saved gid is set appropriately. */
199 error = setresgid(WHEEL_GID, WHEEL_GID, WHEEL_GID);
209 /* Check that saved uid is not used */
210 error = setresuid(TEST_UID_ONE, TEST_UID_ONE, ROOT_UID);
212 perror("setresuid.1");
219 error = access("test1", R_OK);
221 fprintf(stderr, "saved uid used instead of real uid\n");
225 #ifdef EACCESS_AVAILABLE
226 error = eaccess("test1", R_OK);
228 fprintf(stderr, "saved uid used instead of effective uid\n");
233 error = restoreprivilege();
235 perror("restoreprivilege");
240 error = setresuid(TEST_UID_ONE, TEST_UID_TWO, ROOT_UID);
242 perror("setresid.2");
247 /* Check that the real uid is used, not the effective uid */
248 error = access("test2", R_OK);
250 fprintf(stderr, "Effective uid was used instead of real uid in access().\n");
254 #ifdef EACCESS_AVAILABLE
255 /* Check that the effective uid is used, not the real uid */
256 error = eaccess("test3", R_OK);
258 fprintf(stderr, "Real uid was used instead of effective uid in eaccess().\n");
263 /* Check that the real uid is used, not the effective uid */
264 error = access("test3", R_OK);
266 fprintf(stderr, "Effective uid was used instead of real uid in access().\n");
270 #ifdef EACCESS_AVAILABLE
271 /* Check that the effective uid is used, not the real uid */
272 error = eaccess("test2", R_OK);
274 fprintf(stderr, "Real uid was used instead of effective uid in eaccess().\n");
279 error = restoreprivilege();
281 perror("restoreprivilege");
286 error = setresgid(TEST_GID_ONE, TEST_GID_TWO, WHEEL_GID);
288 perror("setresgid.1");
293 /* Set non-root effective uid to avoid excess privilege. */
294 error = setresuid(TEST_UID_ONE, TEST_UID_ONE, ROOT_UID);
296 perror("setresuid.3");
301 /* Check that the saved gid is not used */
302 error = access("test4", R_OK);
304 fprintf(stderr, "saved gid used instead of real gid\n");
307 #ifdef EACCESS_AVAILABLE
308 error = eaccess("test4", R_OK);
310 fprintf(stderr, "saved gid used instead of effective gid\n");
315 /* Check that the real gid is used, not the effective gid */
316 error = access("test5", R_OK);
318 fprintf(stderr, "Effective gid was used instead of real gid in access().\n");
322 #ifdef EACCESS_AVAILABLE
323 /* Check that the effective gid is used, not the real gid */
324 error = eaccess("test6", R_OK);
326 fprintf(stderr, "Real gid was used instead of effective gid in eaccess().\n");
331 /* Check that the real gid is used, not the effective gid */
332 error = access("test6", R_OK);
334 fprintf(stderr, "Effective gid was used instead of real gid in access().\n");
338 #ifdef EACCESS_AVAILABLE
339 /* Check that the effective gid is used, not the real gid */
340 error = eaccess("test5", R_OK);
342 fprintf(stderr, "Real gid was used instead of effective gid in eaccess().\n");
347 fprintf(stderr, "%d errors seen.\n", errorseen);
350 * All tests done, restore and clean up