/* * Copyright (c) 2022 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "acl.h" #include <dlfcn.h> #include <fcntl.h> #include <string> #include <sys/xattr.h> #include <unistd.h> #include "gtest/gtest.h" #include "securec.h" using namespace testing::ext; namespace OHOS::Test { using namespace DATABASE_UTILS; static constexpr uint32_t UID = 2024; // 2024 is test uid static constexpr uint32_t TEST_UID = 2025; // 2025 is test uid class AclTest : public testing::Test { public: static constexpr const char *PATH_ABC = "/data/test/abc"; static constexpr const char *PATH_ABC_XIAOMING = "/data/test/abc/xiaoming"; static constexpr const char *PATH_ABC_XIAOMING_TEST = "/data/test/abc/xiaoming/test.txt"; static constexpr const char *DATA = "SetDefaultUserTest"; static void SetUpTestCase(void); static void TearDownTestCase(void); void SetUp(); void TearDown(); void PreOperation() const; }; void AclTest::SetUpTestCase(void) { } void AclTest::TearDownTestCase(void) { } // input testcase setup step,setup invoked before each testcases void AclTest::SetUp(void) { (void)remove(PATH_ABC); } // input testcase teardown step,teardown invoked after each testcases void AclTest::TearDown(void) { (void)remove(PATH_ABC); } void AclTest::PreOperation() const { mode_t mode = S_IRWXU | S_IRWXG | S_IXOTH; // 0771 int res = mkdir(PATH_ABC, mode); EXPECT_EQ(res, 0) << "directory creation failed." << std::strerror(errno); Acl acl(PATH_ABC); acl.SetDefaultUser(UID, Acl::R_RIGHT | Acl::W_RIGHT); acl.SetDefaultGroup(UID, Acl::R_RIGHT | Acl::W_RIGHT); res = mkdir(PATH_ABC_XIAOMING, mode); EXPECT_EQ(res, 0) << "directory creation failed." << std::strerror(errno); int fd = open(PATH_ABC_XIAOMING_TEST, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP); EXPECT_NE(fd, -1) << "open file failed." << std::strerror(errno); res = write(fd, DATA, strlen(DATA)); EXPECT_NE(res, -1) << "write failed." << std::strerror(errno); res = fsync(fd); EXPECT_NE(res, -1) << "fsync failed." << std::strerror(errno); close(fd); } /** * @tc.name: SetDefaultGroup001 * @tc.desc: Set default extended properties for groups. * @tc.type: FUNC * @tc.require: * @tc.author: Jiaxing Chang */ HWTEST_F(AclTest, SetDefaultGroup001, TestSize.Level0) { mode_t mode = S_IRWXU | S_IRWXG | S_IXOTH; // 0771 int res = mkdir(PATH_ABC, mode); EXPECT_EQ(res, 0) << "directory creation failed."; int rc = Acl(PATH_ABC).SetDefaultGroup(UID, Acl::R_RIGHT | Acl::W_RIGHT); EXPECT_EQ(rc, 0); Acl aclNew(PATH_ABC); AclXattrEntry entry(ACL_TAG::GROUP, UID, Acl::R_RIGHT | Acl::W_RIGHT); ASSERT_TRUE(aclNew.HasEntry(entry)); } /** * @tc.name: SetDefaultpUser001 * @tc.desc: Set default extended properties for user. * @tc.type: FUNC * @tc.require: * @tc.author: Jiaxing Chang */ HWTEST_F(AclTest, SetDefaultUser001, TestSize.Level0) { mode_t mode = S_IRWXU | S_IRWXG | S_IXOTH; // 0771 int res = mkdir(PATH_ABC, mode); EXPECT_EQ(res, 0) << "directory creation failed."; int rc = Acl(PATH_ABC).SetDefaultUser(UID, Acl::R_RIGHT | Acl::W_RIGHT); EXPECT_EQ(rc, 0); Acl aclNew(PATH_ABC); AclXattrEntry entry(ACL_TAG::USER, UID, Acl::R_RIGHT | Acl::W_RIGHT); ASSERT_TRUE(aclNew.HasEntry(entry)); } /** * @tc.name: SetDefaultUser002 * @tc.desc: After the main process extends the uid attribute, set this uid to the uid and gid of the child process, * and the child process can access the files created by the main process normally. * @tc.type: FUNC * @tc.require: * @tc.author: Jiaxing Chang */ HWTEST_F(AclTest, SetDefaultUser002, TestSize.Level0) { PreOperation(); int fd[2]; pid_t pid; char buf[100]; int res = pipe(fd); ASSERT_TRUE(res >= 0) << "create pipe failed." << std::strerror(errno); pid = fork(); ASSERT_TRUE(pid >= 0) << "fork failed." << std::strerror(errno); if (pid == 0) { // subprocess // close the read end of the pipeline. close(fd[0]); // redirect standard output to the write end of the pipeline dup2(fd[1], STDOUT_FILENO); auto exitFun = [&fd](const std::string &str, bool isErr) { std::cout << str << (isErr ? std::strerror(errno) : "") << std::endl; close(fd[1]); _exit(0); }; if (setuid(UID) != 0) { exitFun("setuid failed.", true); } if (setgid(UID) != 0) { exitFun("setgid failed.", true); } int file = open(PATH_ABC_XIAOMING_TEST, O_RDWR, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP); if (file == -1) { exitFun("open file failed.", true); } if (read(file, buf, sizeof(buf)) == -1) { close(file); exitFun("read failed.", true); } close(file); exitFun(buf, false); } else { // main process // close the write end of the pipeline. close(fd[1]); int status; res = waitpid(pid, &status, 0); EXPECT_NE(res, -1) << "waitpid falied." << std::strerror(errno); res = memset_s(buf, sizeof(buf), 0, sizeof(buf)); EXPECT_EQ(res, EOK) << "memset_s falied." << std::strerror(errno); res = read(fd[0], buf, sizeof(buf)); EXPECT_NE(res, -1) << "read falied." << std::strerror(errno); EXPECT_EQ(std::string(buf, buf + strlen(buf) - 1), std::string(DATA)) << "buffer:[" << buf << "]"; close(fd[0]); } } /** * @tc.name: AclXattrEntry001 * @tc.desc: Test operator. * @tc.type: FUNC * @tc.require: * @tc.author: SQL */ HWTEST_F(AclTest, AclXattrEntry001, TestSize.Level0) { AclXattrEntry entryA(ACL_TAG::USER, UID, Acl::R_RIGHT | Acl::W_RIGHT); AclXattrEntry entryB(ACL_TAG::USER, UID, Acl::R_RIGHT | Acl::W_RIGHT); EXPECT_TRUE(entryA == entryB); AclXattrEntry entryC(ACL_TAG::USER, TEST_UID, Acl::R_RIGHT | Acl::W_RIGHT); EXPECT_FALSE(entryA == entryC); } /** * @tc.name: AclXattrEntry002 * @tc.desc: Test IsValid(). * @tc.type: FUNC * @tc.require: * @tc.author: SQL */ HWTEST_F(AclTest, AclXattrEntry002, TestSize.Level0) { AclXattrEntry entryA(ACL_TAG::USER, UID, Acl::R_RIGHT | Acl::W_RIGHT); auto result = entryA.IsValid(); EXPECT_TRUE(result); AclXattrEntry entryB(ACL_TAG::GROUP, UID, Acl::R_RIGHT | Acl::W_RIGHT); result = entryB.IsValid(); EXPECT_TRUE(result); AclXattrEntry entryC(ACL_TAG::UNDEFINED, UID, Acl::R_RIGHT | Acl::W_RIGHT); result = entryC.IsValid(); EXPECT_FALSE(result); } /** * @tc.name: ACL_PERM001 * @tc.desc: Test ACL_PERM. * @tc.type: FUNC * @tc.require: * @tc.author: SQL */ HWTEST_F(AclTest, ACL_PERM001, TestSize.Level0) { ACL_PERM perm1; perm1.SetR(); perm1.SetW(); ACL_PERM perm2; perm2.SetE(); perm1.Merge(perm2); EXPECT_TRUE(perm1.IsReadable()); EXPECT_TRUE(perm1.IsWritable()); EXPECT_TRUE(perm1.IsExecutable()); } } // namespace OHOS::Test