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