1 /* 2 * Copyright (C) 2024 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16 #ifndef OHOS_DISTRIBUTED_DATA_DATABASE_UTILS_ACL_H 17 #define OHOS_DISTRIBUTED_DATA_DATABASE_UTILS_ACL_H 18 19 #include <memory> 20 #include <set> 21 #include <stddef.h> 22 #include <stdint.h> 23 #include <string> 24 25 #include "visibility.h" 26 namespace OHOS { 27 namespace DATABASE_UTILS { 28 /* 29 * ACL tag values 30 */ 31 enum class ACL_TAG : uint16_t { 32 UNDEFINED = 0x00, 33 USER_OBJ = 0x01, 34 USER = 0x02, 35 GROUP_OBJ = 0x04, 36 GROUP = 0x08, 37 MASK = 0x10, 38 OTHER = 0x20, 39 }; 40 41 /* 42 * ACL perm values 43 */ 44 class ACL_PERM { 45 public: 46 uint16_t value_ = 0; 47 enum Value : uint16_t { 48 READ = 0x04, 49 WRITE = 0x02, 50 EXECUTE = 0x01, 51 }; 52 53 public: 54 ACL_PERM() = default; ACL_PERM(const uint16_t x)55 ACL_PERM(const uint16_t x) 56 { 57 value_ = (x & READ) | (x & WRITE) | (x & EXECUTE); 58 } SetR()59 void SetR() { value_ |= READ; } SetW()60 void SetW() { value_ |= WRITE; } SetE()61 void SetE() { value_ |= EXECUTE; } IsReadable()62 bool IsReadable() const { return (value_ & READ) == READ; } IsWritable()63 bool IsWritable() const { return (value_ & WRITE) == WRITE; } IsExecutable()64 bool IsExecutable() const { return (value_ & EXECUTE) == EXECUTE; } Merge(const ACL_PERM & acl_perm)65 void Merge(const ACL_PERM &acl_perm) { value_ |= acl_perm.value_; } 66 }; 67 68 69 /* 70 * ACL data structure 71 */ 72 struct AclXattrHeader { 73 static constexpr uint32_t ACL_EA_VERSION = 0x0002; 74 uint32_t version = ACL_EA_VERSION; 75 }; 76 77 struct AclXattrEntry { 78 static constexpr uint32_t ACL_UNDEFINED_ID = static_cast<uint32_t>(-1); 79 ACL_TAG tag_ = ACL_TAG::UNDEFINED; 80 ACL_PERM perm_ = {}; 81 uint32_t id_ = ACL_UNDEFINED_ID; 82 AclXattrEntryAclXattrEntry83 AclXattrEntry(const ACL_TAG tag, const uint32_t id, const ACL_PERM mode) : tag_(tag), perm_(mode), id_(id) 84 { 85 } 86 IsValidAclXattrEntry87 bool IsValid() const 88 { 89 if (tag_ == ACL_TAG::USER || tag_ == ACL_TAG::GROUP) { 90 return id_ != ACL_UNDEFINED_ID; 91 } 92 return tag_ != ACL_TAG::UNDEFINED; 93 } 94 95 bool operator<(const AclXattrEntry &rhs) const 96 { 97 if (tag_ == rhs.tag_) { 98 return id_ < rhs.id_; 99 } 100 return tag_ < rhs.tag_; 101 } 102 103 bool operator==(const AclXattrEntry &rhs) const 104 { 105 return tag_ == rhs.tag_ && perm_.value_ == rhs.perm_.value_ && id_ == rhs.id_; 106 } 107 108 friend inline bool operator<(const AclXattrEntry &lhs, const ACL_TAG &rhs) 109 { 110 return lhs.tag_ < rhs; 111 } 112 113 friend inline bool operator<(const ACL_TAG &lhs, const AclXattrEntry &rhs) 114 { 115 return lhs < rhs.tag_; 116 } 117 }; 118 119 class Acl { 120 public: 121 static constexpr uint16_t R_RIGHT = 4; 122 static constexpr uint16_t W_RIGHT = 2; 123 static constexpr uint16_t E_RIGHT = 1; 124 125 API_EXPORT Acl(const std::string &path); 126 Acl(); 127 API_EXPORT ~Acl(); 128 API_EXPORT int32_t SetDefaultGroup(const uint32_t gid, const uint16_t mode); 129 API_EXPORT int32_t SetDefaultUser(const uint32_t uid, const uint16_t mode); 130 // just for Acl Test 131 bool HasEntry(const AclXattrEntry &entry); 132 133 private: 134 /* 135 * ACL extended attributes (xattr) names 136 */ 137 static constexpr const char *ACL_XATTR_DEFAULT = "system.posix_acl_default"; 138 static constexpr int32_t E_OK = 0; 139 static constexpr int32_t E_ERROR = -1; 140 static constexpr int32_t USER_OFFSET = 6; 141 static constexpr int32_t GROUP_OFFSET = 3; 142 static constexpr int32_t BUF_SIZE = 400; 143 static constexpr size_t ENTRIES_MAX_NUM = 100; // just heuristic 144 static constexpr size_t BUF_MAX_SIZE = sizeof(AclXattrHeader) + sizeof(AclXattrEntry) * ENTRIES_MAX_NUM; 145 bool IsEmpty(); 146 int32_t SetDefault(); 147 void AclFromMode(); 148 void AclFromDefault(); 149 void CompareInsertEntry(const AclXattrEntry &entry); 150 ACL_PERM ReCalcMaskPerm(); 151 std::unique_ptr<char[]> Serialize(uint32_t &bufSize); 152 int DeSerialize(const char *p, int32_t bufSize); 153 int InsertEntry(const AclXattrEntry &entry); 154 AclXattrHeader header_; 155 /* 156 * Only one entry should exist for the following types: 157 * ACL_USER_OBJ 158 * ACL_GROUP_OBJ 159 * ACL_MASK 160 * ACL_OTHER 161 * While for these types, multiple entries could exist, but one entry 162 * for each id (i.e. uid/gid): 163 * ACL_USER 164 * ACL_GROUP 165 */ 166 std::set<AclXattrEntry, std::less<>> entries_; 167 unsigned maskDemand_ = 0; 168 std::string path_; 169 bool hasError_ = false; 170 }; 171 } // DATABASE_UTILS 172 } // namespace OHOS 173 174 #endif // OHOS_DISTRIBUTED_DATA_DATABASE_UTILS_ACL_H