• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2025 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License"){return 0;}
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 #define MLOG_TAG "MediaPermissionCheck"
16 #include <string>
17 #include "media_permission_check.h"
18 #include "media_composite_permission_check.h"
19 #include "media_system_api_permission_check.h"
20 #include "media_private_permission_check.h"
21 #include "media_read_permission_check.h"
22 #include "media_write_permission_check.h"
23 #include "media_cloudfile_sync_permission_check.h"
24 #include "media_cloud_permission_check.h"
25 #include "media_file_utils.h"
26 #include "permission_common.h"
27 #include "medialibrary_data_manager.h"
28 #include "file_asset.h"
29 #include "parameters.h"
30 #include "media_db_permission_check.h"
31 
32 using namespace std;
33 using namespace OHOS::Media;
34 using namespace OHOS::DataShare;
35 using namespace OHOS::Security::AccessToken;
36 namespace OHOS::Media {
37 std::unordered_map<PermissionType, std::shared_ptr<PermissionCheck>> PermissionCheck::permissionRegistry = {
38     {SYSTEMAPI_PERM, std::make_shared<SystemApiPermissionCheck>()},
39     {PRIVATE_PERM, std::make_shared<PrivatePermissionCheck>()},
40     {READ_PERM, std::make_shared<ReadCompositePermCheck>()},
41     {WRITE_PERM, std::make_shared<WriteCompositePermCheck>()},
42     {CLOUDFILE_SYNC, std::make_shared<CloudFileSyncPermissionCheck>()},
43     {CLOUD_READ, std::make_shared<CloudReadPermissionCheck>()},
44     {CLOUD_WRITE, std::make_shared<CloudWritePermissionCheck>()}
45 };
46 
CollectPermissionInfo(MediaLibraryCommand & cmd,const string & mode,const bool permGranted,PermissionUsedType type)47 static void CollectPermissionInfo(MediaLibraryCommand &cmd, const string &mode,
48     const bool permGranted, PermissionUsedType type)
49 {
50     if ((cmd.GetOprnObject() == OperationObject::FILESYSTEM_PHOTO) ||
51         (cmd.GetOprnObject() == OperationObject::THUMBNAIL) ||
52         (cmd.GetOprnObject() == OperationObject::THUMBNAIL_ASTC)) {
53         CHECK_AND_EXECUTE(mode.find("r") == string::npos,
54             PermissionUtils::CollectPermissionInfo(PERM_READ_IMAGEVIDEO, permGranted, type));
55         CHECK_AND_EXECUTE(mode.find("w") == string::npos,
56             PermissionUtils::CollectPermissionInfo(PERM_WRITE_IMAGEVIDEO, permGranted, type));
57     }
58 }
59 
VerifyOpenFilePermissions(uint32_t businessCode,const PermissionHeaderReq & data)60 int32_t PermissionCheck::VerifyOpenFilePermissions(uint32_t businessCode, const PermissionHeaderReq &data)
61 {
62     std::string openUri = data.getOpenUri();
63     std::string mode = data.getOpenMode();
64     std::vector<PermissionType> openFileToPermissions;
65     openFileToPermissions.push_back(SYSTEMAPI_PERM);
66     Uri uri(openUri);
67 #ifdef MEDIALIBRARY_COMPATIBILITY
68     string realUriStr = MediaFileUtils::GetRealUriFromVirtualUri(uri.ToString());
69     Uri realUri(realUriStr);
70     MediaLibraryCommand command(realUri, Media::OperationType::OPEN);
71 #else
72     MediaLibraryCommand command(uri, Media::OperationType::OPEN);
73 #endif
74     transform(mode.begin(), mode.end(), mode.begin(), ::tolower);
75     if (mode.find('r') != string::npos) {
76         openFileToPermissions.push_back(READ_PERM);
77     }
78     if (mode.find('w') != string::npos) {
79         openFileToPermissions.push_back(WRITE_PERM);
80     }
81 
82     auto permissionCheck = std::make_shared<SinglePermissionCheck>();
83     for (const auto& permKey : openFileToPermissions) {
84         auto check = PermissionCheck::permissionRegistry[permKey];
85         if (check) {
86             permissionCheck->AddCheck(check);
87         }
88     }
89     auto ret = permissionCheck->CheckPermission(businessCode, data);
90     if (ret != E_SUCCESS) {
91         MEDIA_ERR_LOG("Permission Denied! err = %{public}d", ret);
92         CollectPermissionInfo(command, mode, false,
93             PermissionUsedTypeValue::SECURITY_COMPONENT_TYPE);
94         return E_PERMISSION_DENIED;
95     }
96     MEDIA_INFO_LOG("VerifyPermissions API code=%{public}d success", businessCode);
97     return E_SUCCESS;
98 }
99 
GetNeedPermissionCheck() const100 bool PermissionCheck::GetNeedPermissionCheck() const
101 {
102     return needPermissionCheck_;
103 }
SetNeedPermissionCheck(bool needPermissionCheck)104 void PermissionCheck::SetNeedPermissionCheck(bool needPermissionCheck)
105 {
106     needPermissionCheck_ = needPermissionCheck;
107 }
108 
BuildPermissionCheckChain(uint32_t businessCode,const PermissionHeaderReq & data)109 std::shared_ptr<PermissionCheck> PermissionCheck::BuildPermissionCheckChain(uint32_t businessCode,
110     const PermissionHeaderReq &data)
111 {
112     std::vector<std::vector<PermissionType>> ruleLists = data.getPermissionPolicy();
113 
114     bool needPermissionCheck = true;
115     if (ruleLists.empty()) {
116         needPermissionCheck = false;
117     } else {
118         needPermissionCheck = false;
119         for (const auto& ruleList : ruleLists) {
120             if (!ruleList.empty()) {
121                 needPermissionCheck = true;
122                 break;
123             }
124         }
125     }
126 
127     auto compositePermChain = std::make_shared<CompositePermissionCheck>();
128     compositePermChain->SetNeedPermissionCheck(needPermissionCheck);
129     if (!needPermissionCheck) {
130         return compositePermChain;
131     }
132 
133     for (const auto& ruleList : ruleLists) {
134         if (ruleList.empty()) {
135             continue;
136         }
137         auto singlePermCheck = std::make_shared<SinglePermissionCheck>();
138         for (const auto& permKey : ruleList) {
139             auto check = PermissionCheck::permissionRegistry[permKey];
140             if (check) {
141                 singlePermCheck->AddCheck(check);
142             }
143         }
144         compositePermChain->AddCheck(singlePermCheck);
145     }
146     MEDIA_DEBUG_LOG("BuildPermissionCheckChain: %{public}d end", businessCode);
147     return compositePermChain;
148 }
149 
VerifyPermissions(uint32_t businessCode,const PermissionHeaderReq & data)150 int32_t PermissionCheck::VerifyPermissions(uint32_t businessCode, const PermissionHeaderReq &data)
151 {
152     MEDIA_DEBUG_LOG("VerifyPermissions API code=%{public}d", businessCode);
153     if (businessCode == static_cast<uint32_t>(MediaLibraryBusinessCode::PAH_OPEN)) {
154         auto ret = VerifyOpenFilePermissions(businessCode, data);
155         MEDIA_INFO_LOG("Verify OpenFile Permissions ret=%{public}d, API code=%{public}d", ret, businessCode);
156         CHECK_AND_RETURN_RET((ret == E_SUCCESS), E_PERMISSION_DENIED);
157         return E_SUCCESS;
158     }
159 
160     auto permissionCheck = BuildPermissionCheckChain(businessCode, data);
161     if (permissionCheck == nullptr) {
162         MEDIA_DEBUG_LOG("%{public}s permissionCheck is nullptr", __func__);
163         return E_PERMISSION_DENIED;
164     }
165     if (!permissionCheck->GetNeedPermissionCheck()) {
166         MEDIA_INFO_LOG("No Need Permission Check, API code=%{public}d", businessCode);
167         return E_SUCCESS;
168     }
169     auto ret = permissionCheck->CheckPermission(businessCode, data);
170     if (ret != E_SUCCESS) {
171         MEDIA_DEBUG_LOG("checkPermission API code=%{public}d fail, err=%{public}d", businessCode, ret);
172         // if bypass success, return E_PERMISSION_DB_BYPASS
173         CHECK_AND_RETURN_RET(!data.getIsDBBypass(), DbPermissionCheck::CheckDBPermissionBypass(businessCode, data));
174     } else {
175         MEDIA_INFO_LOG("VerifyPermissions API code=%{public}d success", businessCode);
176     }
177     return ret;
178 }
179 
180 } // namespace OHOS::Media
181