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