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