/* * An implementation of access(2) but using the effective user value * instead of the real one. Also avoids false positives for root when * asking for execute permissions, which appear in SunOS. */ atf_error_t atf_fs_eaccess(const atf_fs_path_t *p, int mode) { atf_error_t err; struct stat st; bool ok; PRE(mode & atf_fs_access_f || mode & atf_fs_access_r || mode & atf_fs_access_w || mode & atf_fs_access_x); if (lstat(atf_fs_path_cstring(p), &st) == -1) { err = atf_libc_error(errno, "Cannot get information from file %s", atf_fs_path_cstring(p)); goto out; } err = atf_no_error(); /* Early return if we are only checking for existence and the file * exists (stat call returned). */ if (mode & atf_fs_access_f) goto out; ok = false; if (atf_user_is_root()) { if (!ok && !(mode & atf_fs_access_x)) { /* Allow root to read/write any file. */ ok = true; } if (!ok && (st.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH))) { /* Allow root to execute the file if any of its execution bits * are set. */ ok = true; } } else { if (!ok && (atf_user_euid() == st.st_uid)) { ok = ((mode & atf_fs_access_r) && (st.st_mode & S_IRUSR)) || ((mode & atf_fs_access_w) && (st.st_mode & S_IWUSR)) || ((mode & atf_fs_access_x) && (st.st_mode & S_IXUSR)); } if (!ok && atf_user_is_member_of_group(st.st_gid)) { ok = ((mode & atf_fs_access_r) && (st.st_mode & S_IRGRP)) || ((mode & atf_fs_access_w) && (st.st_mode & S_IWGRP)) || ((mode & atf_fs_access_x) && (st.st_mode & S_IXGRP)); } if (!ok && ((atf_user_euid() != st.st_uid) && !atf_user_is_member_of_group(st.st_gid))) { ok = ((mode & atf_fs_access_r) && (st.st_mode & S_IROTH)) || ((mode & atf_fs_access_w) && (st.st_mode & S_IWOTH)) || ((mode & atf_fs_access_x) && (st.st_mode & S_IXOTH)); } } if (!ok) err = atf_libc_error(EACCES, "Access check failed"); out: return err; }
ATF_TC_BODY (is_member_of_group, tc) { gid_t gids[NGROUPS_MAX]; gid_t g, maxgid; int ngids; { int i; ngids = getgroups (NGROUPS_MAX, gids); if (ngids == -1) atf_tc_fail ("Call to getgroups failed"); maxgid = 0; for (i = 0; i < ngids; i++) { if (maxgid < gids[i]) maxgid = gids[i]; } printf ("User belongs to %d groups\n", ngids); printf ("Last GID is %d\n", maxgid); } for (g = 0; g < maxgid; g++) { bool found = false; int i; for (i = 0; !found && i < ngids; i++) { if (gids[i] == g) found = true; } if (found) { printf ("Checking if user belongs to group %d\n", g); ATF_REQUIRE (atf_user_is_member_of_group (g)); } else { printf ("Checking if user does not belong to group %d\n", g); ATF_REQUIRE (!atf_user_is_member_of_group (g)); } } }
ATF_TC_BODY(is_member_of_group, tc) { gid_t gids[NGROUPS_MAX]; gid_t g, maxgid; int ngids; const gid_t maxgid_limit = 1 << 16; { int i; ngids = getgroups(NGROUPS_MAX, gids); if (ngids == -1) atf_tc_fail("Call to getgroups failed"); maxgid = 0; for (i = 0; i < ngids; i++) { printf("User group %d is %u\n", i, gids[i]); if (maxgid < gids[i]) maxgid = gids[i]; } printf("User belongs to %d groups\n", ngids); printf("Last GID is %u\n", maxgid); } if (maxgid > maxgid_limit) { printf("Test truncated from %u groups to %u to keep the run time " "reasonable enough\n", maxgid, maxgid_limit); maxgid = maxgid_limit; } for (g = 0; g < maxgid; g++) { bool found = false; int i; for (i = 0; !found && i < ngids; i++) { if (gids[i] == g) found = true; } if (found) { printf("Checking if user belongs to group %d\n", g); ATF_REQUIRE(atf_user_is_member_of_group(g)); } else { printf("Checking if user does not belong to group %d\n", g); ATF_REQUIRE(!atf_user_is_member_of_group(g)); } } }