1 /*
2  * Copyright (c) 2022 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 #ifndef OHOS_STORAGE_DAEMON_ACL_H
16 #define OHOS_STORAGE_DAEMON_ACL_H
17 
18 #include <iosfwd>
19 #include <set>
20 #include <functional>
21 
22 namespace OHOS {
23 namespace StorageDaemon {
24 /*
25  * ACL extended attributes (xattr) names
26  */
27 constexpr const char *ACL_XATTR_ACCESS  = "system.posix_acl_access";
28 constexpr const char *ACL_XATTR_DEFAULT = "system.posix_acl_default";
29 
30 /*
31  * ACL tag values
32  */
33 enum class ACL_TAG : uint16_t {
34     UNDEFINED = 0x00,
35     USER_OBJ  = 0x01,
36     USER      = 0x02,
37     GROUP_OBJ = 0x04,
38     GROUP     = 0x08,
39     MASK      = 0x10,
40     OTHER     = 0x20,
41 };
42 
43 /*
44  * ACL perm values
45  */
46 class ACL_PERM {
47     uint16_t value = 0;
48     enum Value : uint16_t {
49         READ    = 0x04,
50         WRITE   = 0x02,
51         EXECUTE = 0x01,
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()
60     {
61         value |= READ;
62     }
SetW()63     void SetW()
64     {
65         value |= WRITE;
66     }
SetE()67     void SetE()
68     {
69         value |= EXECUTE;
70     }
IsReadable()71     bool IsReadable() const
72     {
73         return value & READ;
74     }
IsWritable()75     bool IsWritable() const
76     {
77         return value & WRITE;
78     }
IsExecutable()79     bool IsExecutable() const
80     {
81         return value & EXECUTE;
82     }
Merge(const ACL_PERM & acl_perm)83     void Merge(const ACL_PERM &acl_perm)
84     {
85         value |= acl_perm.value;
86     }
87 };
88 
89 /*
90  * Other constants
91  */
92 constexpr uint32_t ACL_EA_VERSION = 0x0002;
93 constexpr uint32_t ACL_UNDEFINED_ID = (uint32_t)-1;
94 
95 /*
96  * ACL data structure
97  */
98 struct AclXattrHeader {
99     uint32_t version = ACL_EA_VERSION;
100 };
101 
102 struct AclXattrEntry {
103     ACL_TAG tag = ACL_TAG::UNDEFINED;
104     ACL_PERM perm = {};
105     uint32_t id = ACL_UNDEFINED_ID;
IsValidAclXattrEntry106     bool IsValid() const
107     {
108         if (tag == ACL_TAG::USER || tag == ACL_TAG::GROUP) {
109             return id != ACL_UNDEFINED_ID;
110         }
111         return tag != ACL_TAG::UNDEFINED;
112     }
113     bool operator<(const AclXattrEntry &rhs) const
114     {
115         if (tag == rhs.tag) {
116             return id < rhs.id;
117         }
118         return tag < rhs.tag;
119     }
120     friend inline bool operator<(const AclXattrEntry &lhs, const ACL_TAG &rhs)
121     {
122         return lhs.tag < rhs;
123     }
124     friend inline bool operator<(const ACL_TAG &lhs, const AclXattrEntry &rhs)
125     {
126         return lhs < rhs.tag;
127     }
128 };
129 
130 class Acl {
131     AclXattrHeader header;
132     /*
133      * Only one entry should exist for the following types:
134      *     ACL_USER_OBJ
135      *     ACL_GROUP_OBJ
136      *     ACL_MASK
137      *     ACL_OTHER
138      * While for these types, multiple entries could exist, but one entry
139      * for each id (i.e. uid/gid):
140      *     ACL_USER
141      *     ACL_GROUP
142      */
143     std::set<AclXattrEntry, std::less<>> entries;
144     char *buf = nullptr;
145     unsigned maskDemand = 0;
146     constexpr static size_t ENTRIES_MAX_NUM = 100; // just heuristic
147     constexpr static size_t BUF_MAX_SIZE = sizeof(AclXattrHeader) + sizeof(AclXattrEntry) * ENTRIES_MAX_NUM;
148     ACL_PERM ReCalcMaskPerm();
149 public:
150     bool IsEmpty();
151     bool IsValid();
152     int InsertEntry(const AclXattrEntry &entry);
153     char *Serialize(size_t &bufSize);
154     int DeSerialize(const char *p, size_t size);
155     ~Acl();
156 private:
157     void CompareInsertEntry(const AclXattrEntry &entry);
158     void SetMaskEntry();
159 };
160 
161 int AclSetDefault(const std::string &targetFile, const std::string &entryTxt);
162 } // STORAGE_DAEMON
163 } // OHOS
164 
165 #endif // OHOS_STORAGE_DAEMON_ACL_H
166