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