1 /*
2  * Copyright (C) 2023 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_MEDIALIBRARY_ACL_H
17 #define OHOS_MEDIALIBRARY_ACL_H
18 
19 #include <functional>
20 #include <iosfwd>
21 #include <set>
22 #include <string>
23 
24 #include "medialibrary_db_const.h"
25 
26 namespace OHOS {
27 namespace Media {
28 #define EXPORT __attribute__ ((visibility ("default")))
29 /*
30  * ACL extended attributes (xattr) names
31  */
32 constexpr const char *ACL_XATTR_ACCESS = "system.posix_acl_access";
33 constexpr const char *ACL_XATTR_DEFAULT = "system.posix_acl_default";
34 
35 /*
36  * ACL tag values
37  */
38 enum class ACL_TAG : uint16_t {
39     UNDEFINED = 0x00,
40     USER_OBJ  = 0x01,
41     USER      = 0x02,
42     GROUP_OBJ = 0x04,
43     GROUP     = 0x08,
44     MASK      = 0x10,
45     OTHER     = 0x20,
46 };
47 
48 /*
49  * ACL perm values
50  */
51 class ACL_PERM {
52     uint16_t value = 0;
53 public:
54     enum Value : uint16_t {
55         READ    = 0x04,
56         WRITE   = 0x02,
57         EXECUTE = 0x01,
58     };
59     ACL_PERM() = default;
ACL_PERM(const uint16_t x)60     ACL_PERM(const uint16_t x)
61     {
62         value = (x & READ) | (x & WRITE) | (x & EXECUTE);
63     }
SetRead()64     void SetRead()
65     {
66         value |= READ;
67     }
SetWrite()68     void SetWrite()
69     {
70         value |= WRITE;
71     }
SetExecute()72     void SetExecute()
73     {
74         value |= EXECUTE;
75     }
IsReadable()76     bool IsReadable() const
77     {
78         return value & READ;
79     }
IsWritable()80     bool IsWritable() const
81     {
82         return value & WRITE;
83     }
IsExecutable()84     bool IsExecutable() const
85     {
86         return value & EXECUTE;
87     }
Merge(const ACL_PERM & acl_perm)88     void Merge(const ACL_PERM &acl_perm)
89     {
90         value |= acl_perm.value;
91     }
uint16_t()92     operator uint16_t() const
93     {
94         return value;
95     }
96 };
97 
98 /*
99  * Other constants
100  */
101 constexpr uint32_t ACL_EA_VERSION = 0x0002;
102 constexpr uint32_t ACL_UNDEFINED_ID = (uint32_t)-1;
103 constexpr uint32_t THUMB_ACL_GROUP = 2008;
104 constexpr uint32_t MEDIA_DB_ACL_GROUP = 3008;
105 constexpr uint32_t DDMS_ACL_GROUP = 3012;
106 
107 EXPORT const std::string THUMB_DIR = "/storage/cloud/files/.thumbs/Photo";
108 EXPORT const std::string RDB_DIR = MEDIA_DB_DIR + "/rdb";
109 EXPORT const std::string KVDB_DIR = MEDIA_DB_DIR + "/kvdb";
110 /*
111  * ACL data structure
112  */
113 struct AclXattrHeader {
114     uint32_t version = ACL_EA_VERSION;
115 };
116 
117 struct AclXattrEntry {
118     ACL_TAG tag = ACL_TAG::UNDEFINED;
119     ACL_PERM perm = {};
120     uint32_t id = ACL_UNDEFINED_ID;
IsValidAclXattrEntry121     bool IsValid() const
122     {
123         if (tag == ACL_TAG::USER || tag == ACL_TAG::GROUP) {
124             return id != ACL_UNDEFINED_ID;
125         }
126         return tag != ACL_TAG::UNDEFINED;
127     }
128     bool operator<(const AclXattrEntry &rhs) const
129     {
130         if (tag == rhs.tag) {
131             return id < rhs.id;
132         }
133         return tag < rhs.tag;
134     }
135     friend inline bool operator<(const AclXattrEntry &lhs, const ACL_TAG &rhs)
136     {
137         return lhs.tag < rhs;
138     }
139     friend inline bool operator<(const ACL_TAG &lhs, const AclXattrEntry &rhs)
140     {
141         return lhs < rhs.tag;
142     }
143 };
144 
145 class Acl {
146 public:
147     EXPORT bool IsEmpty();
148     EXPORT bool IsValid();
149     EXPORT int InsertEntry(const AclXattrEntry &entry);
150     EXPORT char *Serialize(size_t &bufSize);
151     EXPORT int DeSerialize(const char* aclHead, size_t size);
152 
153     EXPORT static int32_t AclSetDefault();
154     EXPORT static int32_t AclSetDatabase();
155     EXPORT static int32_t AclSetSlaveDatabase();
156     EXPORT static int32_t EntryInsert(AclXattrEntry& entry, const std::string& path, const char* aclAttrName);
157     EXPORT static int32_t RecursiveEnableAcl(const std::string& path, const char* aclAttrName,
158         const uint16_t& permission, uint32_t groupId);
159     EXPORT static int32_t EnableAcl(const std::string& path, const char* aclAttrName,
160         const uint16_t& permission, uint32_t groupId);
161     EXPORT void Print(const std::string& path);
162     EXPORT ~Acl();
163 private:
164     void CompareInsertEntry(const AclXattrEntry &entry);
165 
166     AclXattrHeader header;
167     /*
168      * Only one entry should exist for the following types:
169      *     ACL_USER_OBJ
170      *     ACL_GROUP_OBJ
171      *     ACL_MASK
172      *     ACL_OTHER
173      * While for these types, multiple entries could exist, but one entry
174      * for each id (i.e. uid/gid):
175      *     ACL_USER
176      *     ACL_GROUP
177      */
178     std::set<AclXattrEntry, std::less<>> entries;
179     char *buf = nullptr;
180     unsigned maskDemand = 0;
181     static constexpr size_t ENTRIES_MAX_NUM = 100; // just heuristic
182     static constexpr size_t BUF_MAX_SIZE = sizeof(AclXattrHeader) + sizeof(AclXattrEntry) * ENTRIES_MAX_NUM;
183     ACL_PERM ReCalcMaskPerm();
184 };
185 
186 } // MEDIA
187 } // OHOS
188 
189 #endif // OHOS_MEDIALIBRARY_ACL_H
190