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 #include "uri_utils.h"
17
18 #include "ability_config.h"
19 #include "extension_ability_info.h"
20 #include "hilog_tag_wrapper.h"
21 #include "in_process_call_wrapper.h"
22 #include "ui_extension_utils.h"
23 #include "uri_permission_manager_client.h"
24
25 namespace OHOS {
26 namespace AAFwk {
27 namespace {
28 const std::string PARAMS_URI = "ability.verify.uri";
29 const std::string DISTRIBUTED_FILES_PATH = "/data/storage/el2/distributedfiles/";
30 const int32_t MAX_URI_COUNT = 500;
31 constexpr int32_t API12 = 12;
32 constexpr int32_t API_VERSION_MOD = 100;
33 }
34
UriUtils()35 UriUtils::UriUtils() {}
36
~UriUtils()37 UriUtils::~UriUtils() {}
38
GetInstance()39 UriUtils &UriUtils::GetInstance()
40 {
41 static UriUtils utils;
42 return utils;
43 }
44
GetUriListFromWantDms(const Want & want)45 std::vector<std::string> UriUtils::GetUriListFromWantDms(const Want &want)
46 {
47 std::vector<std::string> uriVec = want.GetStringArrayParam(PARAMS_URI);
48 TAG_LOGD(AAFwkTag::ABILITYMGR, "uriVec size: %{public}zu", uriVec.size());
49 if (uriVec.size() > MAX_URI_COUNT) {
50 TAG_LOGE(AAFwkTag::ABILITYMGR, "size of uri list is more than %{public}u", MAX_URI_COUNT);
51 return {};
52 }
53 std::vector<std::string> validUriVec;
54 for (auto &&str : uriVec) {
55 Uri uri(str);
56 auto &&scheme = uri.GetScheme();
57 TAG_LOGI(AAFwkTag::ABILITYMGR, "uri scheme is %{public}s.", scheme.c_str());
58 // only support file scheme
59 if (scheme != "file") {
60 TAG_LOGW(AAFwkTag::ABILITYMGR, "only support file uri.");
61 continue;
62 }
63 std::string srcPath = uri.GetPath();
64 if (std::filesystem::exists(srcPath) && std::filesystem::is_symlink(srcPath)) {
65 TAG_LOGE(AAFwkTag::ABILITYMGR, "soft links are not allowed.");
66 continue;
67 }
68 std::string absolutePath;
69 if (uri.IsRelative()) {
70 char path[PATH_MAX] = {0};
71 if (realpath(srcPath.c_str(), path) == nullptr) {
72 TAG_LOGE(AAFwkTag::ABILITYMGR, "realpath get failed, errno is %{public}d", errno);
73 continue;
74 }
75 absolutePath = path;
76 } else {
77 absolutePath = srcPath;
78 }
79 if (absolutePath.compare(0, DISTRIBUTED_FILES_PATH.size(), DISTRIBUTED_FILES_PATH) != 0) {
80 TAG_LOGE(AAFwkTag::ABILITYMGR, "uri is not distributed path");
81 continue;
82 }
83 validUriVec.emplace_back(str);
84 }
85 TAG_LOGD(AAFwkTag::ABILITYMGR, "size of vaid uri is %{public}zu", validUriVec.size());
86 return validUriVec;
87 }
88
FilterUriWithPermissionDms(Want & want,uint32_t tokenId)89 void UriUtils::FilterUriWithPermissionDms(Want &want, uint32_t tokenId)
90 {
91 TAG_LOGD(AAFwkTag::ABILITYMGR, "called");
92 if ((want.GetFlags() & (Want::FLAG_AUTH_READ_URI_PERMISSION | Want::FLAG_AUTH_WRITE_URI_PERMISSION)) == 0) {
93 TAG_LOGW(AAFwkTag::ABILITYMGR, "Flag is invalid.");
94 return;
95 }
96 auto uriVec = GetUriListFromWantDms(want);
97 TAG_LOGI(AAFwkTag::ABILITYMGR, "size of uri valid uris is %{public}zu", uriVec.size());
98 if (uriVec.empty()) {
99 TAG_LOGI(AAFwkTag::ABILITYMGR, "uriVec is empty.");
100 want.SetParam(PARAMS_URI, uriVec);
101 return;
102 }
103 auto checkResult = IN_PROCESS_CALL(UriPermissionManagerClient::GetInstance().CheckUriAuthorization(
104 uriVec, want.GetFlags(), tokenId));
105 std::vector<std::string> validUriVec;
106 for (size_t i = 0; i < checkResult.size(); i++) {
107 if (checkResult[i]) {
108 validUriVec.emplace_back(uriVec[i]);
109 }
110 }
111 TAG_LOGI(AAFwkTag::ABILITYMGR, "size of authorized uri is %{public}zu", validUriVec.size());
112 want.SetParam(PARAMS_URI, validUriVec);
113 }
114
CheckNonImplicitShareFileUri(const AbilityRequest & abilityRequest)115 bool UriUtils::CheckNonImplicitShareFileUri(const AbilityRequest &abilityRequest)
116 {
117 if (abilityRequest.appInfo.apiTargetVersion % API_VERSION_MOD <= API12) {
118 return true;
119 }
120 if (abilityRequest.want.GetElement().GetAbilityName().empty()) {
121 return true;
122 }
123 bool isFileUri = !abilityRequest.want.GetUriString().empty() && abilityRequest.want.GetUri().GetScheme() == "file";
124 if (!isFileUri && abilityRequest.want.GetStringArrayParam(AbilityConfig::PARAMS_STREAM).empty()) {
125 return true;
126 }
127 auto flagReadWrite = Want::FLAG_AUTH_READ_URI_PERMISSION | Want::FLAG_AUTH_WRITE_URI_PERMISSION;
128 if ((abilityRequest.want.GetFlags() & flagReadWrite) == 0) {
129 return true;
130 }
131 TAG_LOGE(AAFwkTag::ABILITYMGR, "No permission to share file uri non-implicitly.");
132 return false;
133 }
134
GetPermissionedUriList(const std::vector<std::string> & uriVec,const std::vector<bool> & checkResults,Want & want)135 std::vector<Uri> UriUtils::GetPermissionedUriList(const std::vector<std::string> &uriVec,
136 const std::vector<bool> &checkResults, Want &want)
137 {
138 std::vector<Uri> permissionedUris;
139 if (uriVec.size() != checkResults.size()) {
140 TAG_LOGE(AAFwkTag::ABILITYMGR, "Invalid param: %{public}zu : %{public}zu",
141 uriVec.size(), checkResults.size());
142 return permissionedUris;
143 }
144 // process uri
145 size_t startIndex = 0;
146 if (!want.GetUriString().empty()) {
147 if (checkResults[startIndex]) {
148 permissionedUris.emplace_back(want.GetUri());
149 } else if (want.GetUri().GetScheme() == "file") {
150 // erase uri param
151 want.SetUri("");
152 TAG_LOGI(AAFwkTag::ABILITYMGR, "erase uri param.");
153 }
154 startIndex = 1;
155 }
156 // process param stream
157 std::vector<std::string> paramStreamUris;
158 for (size_t index = startIndex; index < checkResults.size(); index++) {
159 auto uri = Uri(uriVec[index]);
160 if (checkResults[index]) {
161 permissionedUris.emplace_back(uri);
162 paramStreamUris.emplace_back(uriVec[index]);
163 } else if (uri.GetScheme() != "file") {
164 paramStreamUris.emplace_back(uriVec[index]);
165 }
166 }
167 if (paramStreamUris.size() != (checkResults.size() - startIndex)) {
168 // erase old param stream and set new param stream
169 want.RemoveParam(AbilityConfig::PARAMS_STREAM);
170 want.SetParam(AbilityConfig::PARAMS_STREAM, paramStreamUris);
171 TAG_LOGI(AAFwkTag::ABILITYMGR, "startIndex: %{public}zu, uriVec: %{public}zu, paramStreamUris: %{public}zu",
172 startIndex, uriVec.size(), paramStreamUris.size());
173 }
174 return permissionedUris;
175 }
176
GetUriListFromWant(Want & want,std::vector<std::string> & uriVec)177 bool UriUtils::GetUriListFromWant(Want &want, std::vector<std::string> &uriVec)
178 {
179 auto uriStr = want.GetUri().ToString();
180 uriVec = want.GetStringArrayParam(AbilityConfig::PARAMS_STREAM);
181 if (uriVec.empty() && uriStr.empty()) {
182 TAG_LOGW(AAFwkTag::ABILITYMGR, "uriVec empty.");
183 return false;
184 }
185 // process param stream
186 auto paramStreamUriCount = uriVec.size();
187 if (uriStr.empty() && paramStreamUriCount > MAX_URI_COUNT) {
188 TAG_LOGW(AAFwkTag::ABILITYMGR, "uri empty, paream stream counts: %{public}zu", paramStreamUriCount);
189 uriVec.resize(MAX_URI_COUNT);
190 want.RemoveParam(AbilityConfig::PARAMS_STREAM);
191 want.SetParam(AbilityConfig::PARAMS_STREAM, uriVec);
192 }
193 if (!uriStr.empty() && paramStreamUriCount > MAX_URI_COUNT - 1) {
194 TAG_LOGW(AAFwkTag::ABILITYMGR, "paream stream counts: %{public}zu", paramStreamUriCount);
195 uriVec.resize(MAX_URI_COUNT - 1);
196 want.RemoveParam(AbilityConfig::PARAMS_STREAM);
197 want.SetParam(AbilityConfig::PARAMS_STREAM, uriVec);
198 }
199 // process uri
200 if (!uriStr.empty()) {
201 uriVec.insert(uriVec.begin(), uriStr);
202 }
203 return true;
204 }
205
IsGrantUriPermissionFlag(const Want & want)206 bool UriUtils::IsGrantUriPermissionFlag(const Want &want)
207 {
208 return ((want.GetFlags() & (Want::FLAG_AUTH_READ_URI_PERMISSION | Want::FLAG_AUTH_WRITE_URI_PERMISSION)) != 0);
209 }
210
CheckUriPermissionForServiceExtension(Want & want,AppExecFwk::ExtensionAbilityType extensionAbilityType)211 void UriUtils::CheckUriPermissionForServiceExtension(Want &want, AppExecFwk::ExtensionAbilityType extensionAbilityType)
212 {
213 TAG_LOGD(AAFwkTag::ABILITYMGR, "CheckUriPermissionForServiceExtension called.");
214 if (extensionAbilityType != AppExecFwk::ExtensionAbilityType::SERVICE) {
215 return;
216 }
217 CheckUriPermissionForExtension(want, 0);
218 return;
219 }
220
CheckUriPermissionForUIExtension(Want & want,AppExecFwk::ExtensionAbilityType extensionAbilityType,uint32_t tokenId)221 void UriUtils::CheckUriPermissionForUIExtension(Want &want, AppExecFwk::ExtensionAbilityType extensionAbilityType,
222 uint32_t tokenId)
223 {
224 TAG_LOGD(AAFwkTag::ABILITYMGR, "CheckUriPermissionForUIExtension called.");
225 if (!UIExtensionUtils::IsUIExtension(extensionAbilityType)) {
226 return;
227 }
228 CheckUriPermissionForExtension(want, tokenId);
229 return;
230 }
231
CheckUriPermissionForExtension(Want & want,uint32_t tokenId)232 void UriUtils::CheckUriPermissionForExtension(Want &want, uint32_t tokenId)
233 {
234 uint32_t flag = want.GetFlags();
235 if (!IsGrantUriPermissionFlag(want)) {
236 TAG_LOGD(AAFwkTag::ABILITYMGR, "No grant uri flag: %{public}u.", flag);
237 return;
238 }
239 std::vector<std::string> uriVec;
240 if (!UriUtils::GetUriListFromWant(want, uriVec)) {
241 TAG_LOGW(AAFwkTag::ABILITYMGR, "No file uri neet grant.");
242 return;
243 }
244 auto callerTokenId = tokenId > 0 ? tokenId : want.GetIntParam(Want::PARAM_RESV_CALLER_TOKEN, 0);
245 // check uri permission
246 auto checkResults = IN_PROCESS_CALL(UriPermissionManagerClient::GetInstance().CheckUriAuthorization(
247 uriVec, flag, callerTokenId));
248 // remove unpermissioned uri from want
249 UriUtils::GetInstance().GetPermissionedUriList(uriVec, checkResults, want);
250 return;
251 }
252
IsPermissionPreCheckedType(AppExecFwk::ExtensionAbilityType extensionAbilityType)253 bool UriUtils::IsPermissionPreCheckedType(AppExecFwk::ExtensionAbilityType extensionAbilityType)
254 {
255 return extensionAbilityType == AppExecFwk::ExtensionAbilityType::SERVICE ||
256 UIExtensionUtils::IsUIExtension(extensionAbilityType);
257 }
258 } // AAFwk
259 } // OHOS