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 #define MLOG_TAG "ReadWritePermissionHandler"
17
18 #include "read_write_permission_handler.h"
19
20 #include <cstdlib>
21
22 #include "media_file_uri.h"
23 #include "media_file_utils.h"
24 #include "medialibrary_bundle_manager.h"
25 #include "medialibrary_rdbstore.h"
26 #include "rdb_utils.h"
27 #include "medialibrary_uripermission_operations.h"
28 #include "permission_utils.h"
29 #include "system_ability_definition.h"
30 #ifdef MEDIALIBRARY_SECURITY_OPEN
31 #include "sec_comp_kit.h"
32 #endif
33
34 using namespace std;
35
36 namespace OHOS::Media {
37
ContainsFlag(const string & mode,const char flag)38 static inline bool ContainsFlag(const string &mode, const char flag)
39 {
40 return mode.find(flag) != string::npos;
41 }
42
SystemApiCheck(MediaLibraryCommand & cmd)43 static int32_t SystemApiCheck(MediaLibraryCommand &cmd)
44 {
45 static const set<OperationObject> SYSTEM_API_OBJECTS = {
46 OperationObject::UFM_PHOTO,
47 OperationObject::UFM_AUDIO,
48 OperationObject::UFM_ALBUM,
49 OperationObject::UFM_MAP,
50 OperationObject::SMART_ALBUM,
51
52 OperationObject::ALL_DEVICE,
53 OperationObject::ACTIVE_DEVICE,
54 OperationObject::PAH_FORM_MAP,
55 };
56
57 static const set<string> SYSTEM_API_URIS = {
58 // Deleting asset permanently from system is only allowed for system apps.
59 URI_DELETE_PHOTOS,
60 // Deleting asset to trash album directly without a pop-up box is only allowed for system apps.
61 UFM_DELETE_PHOTOS,
62 PAH_DELETE_PHOTOS,
63 };
64
65 OperationObject obj = cmd.GetOprnObject();
66 string uri = cmd.GetUriStringWithoutSegment();
67 if (SYSTEM_API_OBJECTS.find(obj) != SYSTEM_API_OBJECTS.end() ||
68 (SYSTEM_API_URIS.find(uri) != SYSTEM_API_URIS.end())) {
69 if (!PermissionUtils::IsSystemApp()) {
70 MEDIA_ERR_LOG("Systemapi should only be called by system applications!");
71 return E_CHECK_SYSTEMAPP_FAIL;
72 }
73 }
74 return E_SUCCESS;
75 }
76
AddHiddenAlbumPermission(MediaLibraryCommand & cmd,vector<string> & outPerms)77 static inline void AddHiddenAlbumPermission(MediaLibraryCommand &cmd, vector<string> &outPerms)
78 {
79 Media::OperationType type = cmd.GetOprnType();
80 if (type == Media::OperationType::QUERY_HIDDEN) {
81 outPerms.push_back(PERM_MANAGE_PRIVATE_PHOTOS);
82 }
83 }
84
HandleSecurityComponentPermission(MediaLibraryCommand & cmd)85 static int32_t HandleSecurityComponentPermission(MediaLibraryCommand &cmd)
86 {
87 if (cmd.GetUri().ToString().find(OPRN_CREATE_COMPONENT) != string::npos ||
88 cmd.GetUri().ToString().find(OPRN_SAVE_CAMERA_PHOTO_COMPONENT) != string::npos) {
89 #ifdef MEDIALIBRARY_SECURITY_OPEN
90 auto tokenId = PermissionUtils::GetTokenId();
91 if (!Security::SecurityComponent::SecCompKit::VerifySavePermission(tokenId)) {
92 MEDIA_ERR_LOG("Failed to verify save permission of security component");
93 return E_NEED_FURTHER_CHECK;
94 }
95 return E_SUCCESS;
96 #else
97 MEDIA_ERR_LOG("Security component is not existed");
98 return E_NEED_FURTHER_CHECK;
99 #endif
100 }
101 return E_NEED_FURTHER_CHECK;
102 }
103
104
UnifyOprnObject(MediaLibraryCommand & cmd)105 static void UnifyOprnObject(MediaLibraryCommand &cmd)
106 {
107 static const unordered_map<OperationObject, OperationObject> UNIFY_OP_OBJECT_MAP = {
108 { OperationObject::UFM_PHOTO, OperationObject::FILESYSTEM_PHOTO },
109 { OperationObject::UFM_AUDIO, OperationObject::FILESYSTEM_AUDIO },
110 { OperationObject::UFM_ALBUM, OperationObject::PHOTO_ALBUM },
111 { OperationObject::UFM_MAP, OperationObject::PHOTO_MAP },
112 { OperationObject::PAH_PHOTO, OperationObject::FILESYSTEM_PHOTO },
113 { OperationObject::PAH_ALBUM, OperationObject::PHOTO_ALBUM },
114 { OperationObject::PAH_MAP, OperationObject::PHOTO_MAP },
115 { OperationObject::TOOL_PHOTO, OperationObject::FILESYSTEM_PHOTO },
116 { OperationObject::TOOL_AUDIO, OperationObject::FILESYSTEM_AUDIO },
117 { OperationObject::TOOL_ALBUM, OperationObject::PHOTO_ALBUM },
118 };
119
120 OperationObject obj = cmd.GetOprnObject();
121 if (UNIFY_OP_OBJECT_MAP.find(obj) != UNIFY_OP_OBJECT_MAP.end()) {
122 cmd.SetOprnObject(UNIFY_OP_OBJECT_MAP.at(obj));
123 }
124 }
125
PhotoAccessHelperPermCheck(MediaLibraryCommand & cmd,const bool isWrite)126 static int32_t PhotoAccessHelperPermCheck(MediaLibraryCommand &cmd, const bool isWrite)
127 {
128 static const set<OperationObject> PHOTO_ACCESS_HELPER_OBJECTS = {
129 OperationObject::PAH_PHOTO,
130 OperationObject::PAH_ALBUM,
131 OperationObject::PAH_MAP,
132 OperationObject::PAH_FORM_MAP,
133 OperationObject::ANALYSIS_PHOTO_ALBUM,
134 OperationObject::ANALYSIS_PHOTO_MAP,
135 OperationObject::VISION_OCR,
136 OperationObject::VISION_AESTHETICS,
137 OperationObject::VISION_LABEL,
138 OperationObject::VISION_VIDEO_LABEL,
139 OperationObject::VISION_IMAGE_FACE,
140 OperationObject::VISION_VIDEO_FACE,
141 OperationObject::VISION_FACE_TAG,
142 OperationObject::VISION_OBJECT,
143 OperationObject::VISION_RECOMMENDATION,
144 OperationObject::VISION_SEGMENTATION,
145 OperationObject::VISION_COMPOSITION,
146 OperationObject::VISION_SALIENCY,
147 OperationObject::VISION_HEAD,
148 OperationObject::VISION_POSE,
149 OperationObject::VISION_TOTAL,
150 OperationObject::GEO_DICTIONARY,
151 OperationObject::GEO_KNOWLEDGE,
152 OperationObject::GEO_PHOTO,
153 OperationObject::PAH_MULTISTAGES_CAPTURE,
154 OperationObject::STORY_ALBUM,
155 OperationObject::STORY_COVER,
156 OperationObject::STORY_PLAY,
157 OperationObject::USER_PHOTOGRAPHY,
158 OperationObject::PAH_BATCH_THUMBNAIL_OPERATE,
159 OperationObject::INDEX_CONSTRUCTION_STATUS,
160 OperationObject::ANALYSIS_ASSET_SD_MAP,
161 OperationObject::ANALYSIS_ALBUM_ASSET_MAP,
162 };
163
164 int32_t err = HandleSecurityComponentPermission(cmd);
165 if (err == E_SUCCESS || (err != E_SUCCESS && err != E_NEED_FURTHER_CHECK)) {
166 return err;
167 }
168
169 OperationObject obj = cmd.GetOprnObject();
170 if (PHOTO_ACCESS_HELPER_OBJECTS.find(obj) == PHOTO_ACCESS_HELPER_OBJECTS.end()) {
171 return E_NEED_FURTHER_CHECK;
172 }
173 vector<string> perms;
174 AddHiddenAlbumPermission(cmd, perms);
175 perms.push_back(isWrite ? PERM_WRITE_IMAGEVIDEO : PERM_READ_IMAGEVIDEO);
176 return PermissionUtils::CheckCallerPermission(perms) ? E_SUCCESS : E_PERMISSION_DENIED;
177 }
178
UserFileMgrPermissionCheck(MediaLibraryCommand & cmd,const bool isWrite)179 static int32_t UserFileMgrPermissionCheck(MediaLibraryCommand &cmd, const bool isWrite)
180 {
181 static const set<OperationObject> USER_FILE_MGR_OBJECTS = {
182 OperationObject::UFM_PHOTO,
183 OperationObject::UFM_AUDIO,
184 OperationObject::UFM_ALBUM,
185 OperationObject::UFM_MAP,
186 };
187
188 OperationObject obj = cmd.GetOprnObject();
189 if (USER_FILE_MGR_OBJECTS.find(obj) == USER_FILE_MGR_OBJECTS.end()) {
190 return E_NEED_FURTHER_CHECK;
191 }
192
193 int32_t err = HandleSecurityComponentPermission(cmd);
194 if (err == E_SUCCESS || (err != E_SUCCESS && err != E_NEED_FURTHER_CHECK)) {
195 return err;
196 }
197
198 vector<string> perms;
199 if (obj == OperationObject::UFM_AUDIO) {
200 perms.push_back(isWrite ? PERM_WRITE_AUDIO : PERM_READ_AUDIO);
201 } else {
202 perms.push_back(isWrite ? PERM_WRITE_IMAGEVIDEO : PERM_READ_IMAGEVIDEO);
203 }
204 AddHiddenAlbumPermission(cmd, perms);
205 return PermissionUtils::CheckCallerPermission(perms) ? E_SUCCESS : E_PERMISSION_DENIED;
206 }
207
HandleBundlePermCheck()208 static inline int32_t HandleBundlePermCheck()
209 {
210 bool ret = PermissionUtils::CheckCallerPermission(PERMISSION_NAME_WRITE_MEDIA);
211 if (ret) {
212 return E_SUCCESS;
213 }
214
215 return PermissionUtils::CheckHasPermission(WRITE_PERMS_V10) ? E_SUCCESS : E_PERMISSION_DENIED;
216 }
217
HandleNoPermCheck(MediaLibraryCommand & cmd)218 static int32_t HandleNoPermCheck(MediaLibraryCommand &cmd)
219 {
220 static const set<string> NO_NEED_PERM_CHECK_URI = {
221 URI_CLOSE_FILE,
222 MEDIALIBRARY_DIRECTORY_URI,
223 };
224
225 static const set<OperationObject> NO_NEED_PERM_CHECK_OBJ = {
226 OperationObject::ALL_DEVICE,
227 OperationObject::ACTIVE_DEVICE,
228 OperationObject::MISCELLANEOUS,
229 OperationObject::TAB_OLD_PHOTO,
230 };
231
232 string uri = cmd.GetUri().ToString();
233 OperationObject obj = cmd.GetOprnObject();
234 if (NO_NEED_PERM_CHECK_URI.find(uri) != NO_NEED_PERM_CHECK_URI.end() ||
235 NO_NEED_PERM_CHECK_OBJ.find(obj) != NO_NEED_PERM_CHECK_OBJ.end()) {
236 return E_SUCCESS;
237 }
238 return E_NEED_FURTHER_CHECK;
239 }
240
HandleMediaVolumePerm()241 static inline int32_t HandleMediaVolumePerm()
242 {
243 return PermissionUtils::CheckCallerPermission(PERMISSION_NAME_READ_MEDIA) ? E_SUCCESS : E_PERMISSION_DENIED;
244 }
245
246
HandleSpecialObjectPermission(MediaLibraryCommand & cmd,bool isWrite)247 static int32_t HandleSpecialObjectPermission(MediaLibraryCommand &cmd, bool isWrite)
248 {
249 int err = HandleNoPermCheck(cmd);
250 if (err == E_SUCCESS || (err != E_SUCCESS && err != E_NEED_FURTHER_CHECK)) {
251 return err;
252 }
253
254 OperationObject obj = cmd.GetOprnObject();
255 if (obj == OperationObject::MEDIA_VOLUME) {
256 return HandleMediaVolumePerm();
257 } else if (obj == OperationObject::BUNDLE_PERMISSION) {
258 return HandleBundlePermCheck();
259 }
260
261 if (MediaFileUtils::IsCalledBySelf() == E_OK) {
262 return E_SUCCESS;
263 }
264
265 return E_NEED_FURTHER_CHECK;
266 }
267
CheckPermFromUri(MediaLibraryCommand & cmd,bool isWrite)268 static int32_t CheckPermFromUri(MediaLibraryCommand &cmd, bool isWrite)
269 {
270 MEDIA_DEBUG_LOG("uri: %{private}s object: %{public}d, opType: %{public}d isWrite: %{public}d",
271 cmd.GetUri().ToString().c_str(), cmd.GetOprnObject(), cmd.GetOprnType(), isWrite);
272
273 int err = SystemApiCheck(cmd);
274 if (err != E_SUCCESS) {
275 return err;
276 }
277 err = PhotoAccessHelperPermCheck(cmd, isWrite);
278 if (err == E_SUCCESS || (err != E_SUCCESS && err != E_NEED_FURTHER_CHECK)) {
279 UnifyOprnObject(cmd);
280 return err;
281 }
282 err = UserFileMgrPermissionCheck(cmd, isWrite);
283 if (err == E_SUCCESS || (err != E_SUCCESS && err != E_NEED_FURTHER_CHECK)) {
284 UnifyOprnObject(cmd);
285 return err;
286 }
287 err = HandleSpecialObjectPermission(cmd, isWrite);
288 if (err == E_SUCCESS || (err != E_SUCCESS && err != E_NEED_FURTHER_CHECK)) {
289 UnifyOprnObject(cmd);
290 return err;
291 }
292
293 string perm = isWrite ? PERM_WRITE_IMAGEVIDEO : PERM_READ_IMAGEVIDEO;
294 err = PermissionUtils::CheckCallerPermission(perm) ? E_SUCCESS : E_PERMISSION_DENIED;
295 if (err < 0) {
296 return err;
297 }
298 UnifyOprnObject(cmd);
299 return E_SUCCESS;
300 }
301
FillV10Perms(const MediaType mediaType,const bool containsRead,const bool containsWrite,vector<string> & perm)302 static void FillV10Perms(const MediaType mediaType, const bool containsRead, const bool containsWrite,
303 vector<string> &perm)
304 {
305 if (containsRead) {
306 if (mediaType == MEDIA_TYPE_IMAGE || mediaType == MEDIA_TYPE_VIDEO ||
307 mediaType == Media::MEDIA_TYPE_PHOTO || mediaType == Media::MEDIA_TYPE_ALBUM) {
308 perm.push_back(PERM_READ_IMAGEVIDEO);
309 } else if (mediaType == MEDIA_TYPE_AUDIO) {
310 perm.push_back(PERM_READ_AUDIO);
311 } else if (mediaType == MEDIA_TYPE_FILE) {
312 perm.push_back(PERM_READ_IMAGEVIDEO);
313 perm.push_back(PERM_READ_AUDIO);
314 perm.push_back(PERM_READ_DOCUMENT);
315 }
316 }
317 if (containsWrite) {
318 if (mediaType == MEDIA_TYPE_IMAGE || mediaType == MEDIA_TYPE_VIDEO ||
319 mediaType == Media::MEDIA_TYPE_PHOTO || mediaType == Media::MEDIA_TYPE_ALBUM) {
320 perm.push_back(PERM_WRITE_IMAGEVIDEO);
321 } else if (mediaType == MEDIA_TYPE_AUDIO) {
322 perm.push_back(PERM_WRITE_AUDIO);
323 } else if (mediaType == MEDIA_TYPE_FILE) {
324 perm.push_back(PERM_WRITE_IMAGEVIDEO);
325 perm.push_back(PERM_WRITE_AUDIO);
326 perm.push_back(PERM_WRITE_DOCUMENT);
327 }
328 }
329 }
330
CheckOpenFilePermission(MediaLibraryCommand & cmd,PermParam & permParam)331 static int32_t CheckOpenFilePermission(MediaLibraryCommand &cmd, PermParam &permParam)
332 {
333 MEDIA_DEBUG_LOG("uri: %{private}s mode: %{private}s",
334 cmd.GetUri().ToString().c_str(), permParam.openFileNode.c_str());
335 if (MediaFileUtils::IsCalledBySelf() == E_OK) {
336 return E_SUCCESS;
337 }
338 MediaType mediaType = MediaFileUri::GetMediaTypeFromUri(cmd.GetUri().ToString());
339 const bool containsRead = ContainsFlag(permParam.openFileNode, 'r');
340 const bool containsWrite = ContainsFlag(permParam.openFileNode, 'w');
341 vector<string> perms;
342 FillV10Perms(mediaType, containsRead, containsWrite, perms);
343 if ((cmd.GetOprnObject() == OperationObject::FILESYSTEM_PHOTO) ||
344 (cmd.GetOprnObject() == OperationObject::THUMBNAIL) ||
345 (cmd.GetOprnObject() == OperationObject::THUMBNAIL_ASTC)) {
346 return PermissionUtils::CheckPhotoCallerPermission(perms)? E_SUCCESS : E_PERMISSION_DENIED;
347 }
348 int32_t err = (mediaType == MEDIA_TYPE_FILE) ?
349 (PermissionUtils::CheckHasPermission(perms) ? E_SUCCESS : E_PERMISSION_DENIED) :
350 (PermissionUtils::CheckCallerPermission(perms) ? E_SUCCESS : E_PERMISSION_DENIED);
351 if (err == E_SUCCESS) {
352 return E_SUCCESS;
353 }
354 perms.clear();
355 if (containsRead) {
356 perms.push_back(PERM_READ_IMAGEVIDEO);
357 }
358 if (containsWrite) {
359 perms.push_back(PERM_WRITE_IMAGEVIDEO);
360 }
361 return PermissionUtils::CheckCallerPermission(perms) ? E_SUCCESS : E_PERMISSION_DENIED;
362 }
363
ExecuteCheckPermission(MediaLibraryCommand & cmd,PermParam & permParam)364 int32_t ReadWritePermissionHandler::ExecuteCheckPermission(MediaLibraryCommand &cmd, PermParam &permParam)
365 {
366 MEDIA_DEBUG_LOG("ReadWritePermissionHandler:isOpenFile=%{public}d", permParam.isOpenFile);
367 if (permParam.isOpenFile) {
368 permParam.isWrite = ContainsFlag(permParam.openFileNode, 'w');
369 return CheckOpenFilePermission(cmd, permParam);
370 }
371 return CheckPermFromUri(cmd, permParam.isWrite);
372 }
373
374 } // namespace name