1 /*
2 * Copyright (c) 2021-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 "distributed_sched_permission.h"
17
18 #include "accesstoken_kit.h"
19 #include "datetime_ex.h"
20 #include "device_auth_defines.h"
21 #include "device_manager.h"
22 #include "device_security_defines.h"
23 #include "device_security_info.h"
24 #include "ipc_skeleton.h"
25 #include "ohos_account_kits.h"
26 #include "os_account_manager.h"
27 #include "string_wrapper.h"
28
29 #include "adapter/dnetwork_adapter.h"
30 #include "bundle/bundle_manager_internal.h"
31 #include "caller_info.h"
32 #include "distributed_sched_adapter.h"
33 #include "distributed_sched_utils.h"
34 #include "dtbschedmgr_device_info_storage.h"
35 #include "dtbschedmgr_log.h"
36 #include "json_util.h"
37
38 namespace OHOS {
39 namespace DistributedSchedule {
40 using namespace OHOS::Security;
41 using namespace AAFwk;
42 using namespace DistributedHardware;
43 namespace {
44 const std::string FOUNDATION_PROCESS_NAME = "foundation";
45 const std::string DMS_API_VERSION = "dmsApiVersion";
46 const std::string DMS_IS_CALLER_BACKGROUND = "dmsIsCallerBackGround";
47 const std::string DMS_MISSION_ID = "dmsMissionId";
48 const std::string DMS_VERSION_ID = "dmsVersion";
49 const std::string PARAMS_URI = "ability.verify.uri";
50 const std::string PARAMS_STREAM = "ability.params.stream";
51 const std::string PERMISSION_START_ABILIIES_FROM_BACKGROUND = "ohos.permission.START_ABILIIES_FROM_BACKGROUND";
52 const std::string PERMISSION_START_ABILITIES_FROM_BACKGROUND = "ohos.permission.START_ABILITIES_FROM_BACKGROUND";
53 const std::string PERMISSION_START_INVISIBLE_ABILITY = "ohos.permission.START_INVISIBLE_ABILITY";
54 const std::string DISTRIBUTED_FILES_PATH = "/data/storage/el2/distributedfiles/";
55 const std::string BUNDLE_NAME_SCENEBOARD = "com.ohos.sceneboard";
56 constexpr int32_t DEFAULT_DMS_API_VERSION = 9;
57 const int DEFAULT_DMS_MISSION_ID = -1;
58 const int FA_MODULE_ALLOW_MIN_API_VERSION = 8;
59 const int DEFAULT_DEVICE_SECURITY_LEVEL = -1;
60 }
61
62 IMPLEMENT_SINGLE_INSTANCE(DistributedSchedPermission);
63
from_json(const nlohmann::json & jsonObject,GroupInfo & groupInfo)64 void from_json(const nlohmann::json& jsonObject, GroupInfo& groupInfo)
65 {
66 const auto &jsonObjectEnd = jsonObject.end();
67 int32_t parseResult = ERR_OK;
68 GetValueIfFindKey<std::string>(jsonObject,
69 jsonObjectEnd,
70 FIELD_GROUP_NAME,
71 groupInfo.groupName,
72 JsonType::STRING,
73 false,
74 parseResult,
75 ArrayType::NOT_ARRAY);
76 GetValueIfFindKey<std::string>(jsonObject,
77 jsonObjectEnd,
78 FIELD_GROUP_ID,
79 groupInfo.groupId,
80 JsonType::STRING,
81 false,
82 parseResult,
83 ArrayType::NOT_ARRAY);
84 GetValueIfFindKey<std::string>(jsonObject,
85 jsonObjectEnd,
86 FIELD_GROUP_OWNER,
87 groupInfo.groupOwner,
88 JsonType::STRING,
89 false,
90 parseResult,
91 ArrayType::NOT_ARRAY);
92 GetValueIfFindKey<int32_t>(jsonObject,
93 jsonObjectEnd,
94 FIELD_GROUP_TYPE,
95 groupInfo.groupType,
96 JsonType::NUMBER,
97 false,
98 parseResult,
99 ArrayType::NOT_ARRAY);
100 GetValueIfFindKey<int32_t>(jsonObject,
101 jsonObjectEnd,
102 FIELD_GROUP_VISIBILITY,
103 groupInfo.groupVisibility,
104 JsonType::NUMBER,
105 false,
106 parseResult,
107 ArrayType::NOT_ARRAY);
108 }
109
CheckSendResultPermission(const AAFwk::Want & want,const CallerInfo & callerInfo,const AccountInfo & accountInfo,AppExecFwk::AbilityInfo & targetAbility)110 int32_t DistributedSchedPermission::CheckSendResultPermission(const AAFwk::Want& want, const CallerInfo& callerInfo,
111 const AccountInfo& accountInfo, AppExecFwk::AbilityInfo& targetAbility)
112 {
113 // 1.check account access permission in no account networking environment.
114 if (!CheckAccountAccessPermission(callerInfo, accountInfo, targetAbility.bundleName)) {
115 HILOGE("CheckAccountAccessPermission denied or failed!");
116 return DMS_ACCOUNT_ACCESS_PERMISSION_DENIED;
117 }
118 // 2.check component access permission, when the ability is not visible.
119 if (!CheckComponentAccessPermission(targetAbility, callerInfo, accountInfo, want)) {
120 HILOGE("CheckComponentAccessPermission denied or failed! the callee component do not have permission");
121 return DMS_COMPONENT_ACCESS_PERMISSION_DENIED;
122 }
123 HILOGI("CheckSendResultPermission success!!");
124 return ERR_OK;
125 }
126
CheckStartPermission(const AAFwk::Want & want,const CallerInfo & callerInfo,const AccountInfo & accountInfo,AppExecFwk::AbilityInfo & targetAbility,bool isSameBundle)127 int32_t DistributedSchedPermission::CheckStartPermission(const AAFwk::Want& want, const CallerInfo& callerInfo,
128 const AccountInfo& accountInfo, AppExecFwk::AbilityInfo& targetAbility, bool isSameBundle)
129 {
130 // 1.check account access permission in no account networking environment.
131 if (!CheckAccountAccessPermission(callerInfo, accountInfo, targetAbility.bundleName)) {
132 HILOGE("CheckAccountAccessPermission denied or failed!");
133 return DMS_ACCOUNT_ACCESS_PERMISSION_DENIED;
134 }
135 // 2.check start control permissions.
136 if (!CheckStartControlPermission(targetAbility, callerInfo, want, isSameBundle)) {
137 HILOGE("CheckStartControlPermission denied or failed! the callee component do not have permission");
138 return DMS_START_CONTROL_PERMISSION_DENIED;
139 }
140 HILOGI("CheckDistributedPermission success!");
141 return ERR_OK;
142 }
143
CheckStartControlPermission(const AppExecFwk::AbilityInfo & targetAbility,const CallerInfo & callerInfo,const AAFwk::Want & want,bool isSameBundle)144 bool DistributedSchedPermission::CheckStartControlPermission(const AppExecFwk::AbilityInfo& targetAbility,
145 const CallerInfo& callerInfo, const AAFwk::Want& want, bool isSameBundle)
146 {
147 HILOGD("Check start control permission enter");
148 return ((want.GetFlags() & AAFwk::Want::FLAG_ABILITY_CONTINUATION) != 0) ?
149 CheckMigrateStartCtrlPer(targetAbility, callerInfo, want, isSameBundle) :
150 CheckCollaborateStartCtrlPer(targetAbility, callerInfo, want);
151 }
152
CheckCollabStartPermission(const AAFwk::Want & want,const CallerInfo & callerInfo,const AccountInfo & accountInfo,AppExecFwk::AbilityInfo & targetAbility)153 int32_t DistributedSchedPermission::CheckCollabStartPermission(const AAFwk::Want& want, const CallerInfo& callerInfo,
154 const AccountInfo& accountInfo, AppExecFwk::AbilityInfo& targetAbility)
155 {
156 // 1.check account access permission in no account networking environment.
157 bool isNewCollab = true;
158 if (!CheckAccountAccessPermission(callerInfo, accountInfo, targetAbility.bundleName, isNewCollab)) {
159 HILOGE("CheckAccountAccessPermission denied or failed!");
160 return DMS_ACCOUNT_ACCESS_PERMISSION_DENIED;
161 }
162 // 2.check start control permissions.
163 if (!CheckCollabStartControlPermission(targetAbility, callerInfo, want)) {
164 HILOGE("CheckCollabStartControlPermission denied or failed! the callee component do not have permission");
165 return DMS_START_CONTROL_PERMISSION_DENIED;
166 }
167 HILOGI("CheckDistributedPermission success!");
168 return ERR_OK;
169 }
170
171
GetAccountInfo(const std::string & remoteNetworkId,const CallerInfo & callerInfo,AccountInfo & accountInfo)172 int32_t DistributedSchedPermission::GetAccountInfo(const std::string& remoteNetworkId,
173 const CallerInfo& callerInfo, AccountInfo& accountInfo)
174 {
175 if (remoteNetworkId.empty()) {
176 HILOGE("remoteNetworkId is empty");
177 return ERR_NULL_OBJECT;
178 }
179 std::string udid = DnetworkAdapter::GetInstance()->GetUdidByNetworkId(remoteNetworkId);
180 if (udid.empty()) {
181 HILOGE("udid is empty");
182 return ERR_NULL_OBJECT;
183 }
184 if (!GetOsAccountData(accountInfo)) {
185 HILOGE("Get Os accountId and userId fail.");
186 return INVALID_PARAMETERS_ERR;
187 }
188
189 #ifdef DMSFWK_SAME_ACCOUNT
190 if (CheckDstSameAccount(remoteNetworkId, accountInfo, callerInfo)) {
191 return ERR_OK;
192 }
193 HILOGI("check same account by DM fail, will try check access Group by hichain");
194 #endif // DMSFWK_SAME_ACCOUNT
195
196 if (GetRelatedGroups(udid, callerInfo.bundleNames, accountInfo)) {
197 return ERR_OK;
198 }
199
200 HILOGI("Check access Group by hichain fail, will try check different account ACL by DM.");
201 if (CheckAclList(remoteNetworkId, accountInfo, callerInfo)) {
202 return ERR_OK;
203 }
204 HILOGE("Check different account ACL by DM fail.");
205 return INVALID_PARAMETERS_ERR;
206 }
207
GetOsAccountData(AccountInfo & dmsAccountInfo)208 bool DistributedSchedPermission::GetOsAccountData(AccountInfo& dmsAccountInfo)
209 {
210 #ifdef OS_ACCOUNT_PART
211 std::vector<int32_t> ids;
212 ErrCode ret = AccountSA::OsAccountManager::QueryActiveOsAccountIds(ids);
213 if (ret != ERR_OK || ids.empty()) {
214 HILOGE("Get userId from active Os AccountIds fail, ret : %{public}d", ret);
215 return false;
216 }
217 dmsAccountInfo.userId = ids[0];
218
219 AccountSA::OhosAccountInfo osAccountInfo;
220 ret = AccountSA::OhosAccountKits::GetInstance().GetOhosAccountInfo(osAccountInfo);
221 if (ret != 0 || osAccountInfo.uid_ == "") {
222 HILOGE("Get accountId from Ohos account info fail, ret: %{public}d.", ret);
223 return false;
224 }
225 dmsAccountInfo.activeAccountId = osAccountInfo.uid_;
226 HILOGI("Get caller dmsAccountInfo OK, accountId %{public}s, userId %{public}s.",
227 GetAnonymStr(dmsAccountInfo.activeAccountId).c_str(), GetAnonymInt32(dmsAccountInfo.userId).c_str());
228 #endif
229 return true;
230 }
231
CheckDstSameAccount(const std::string & dstNetworkId,const AccountInfo & dmsAccountInfo,const CallerInfo & callerInfo)232 bool DistributedSchedPermission::CheckDstSameAccount(const std::string& dstNetworkId,
233 const AccountInfo& dmsAccountInfo, const CallerInfo& callerInfo)
234 {
235 #ifdef DMSFWK_SAME_ACCOUNT
236 DmAccessCaller dmSrcCaller = {
237 .accountId = dmsAccountInfo.activeAccountId,
238 .networkId = callerInfo.sourceDeviceId,
239 .userId = dmsAccountInfo.userId,
240 .tokenId = callerInfo.accessToken,
241 };
242 DmAccessCallee dmDstCallee = {
243 .networkId = dstNetworkId,
244 .peerId = "",
245 };
246 for (const auto& bundleName : callerInfo.bundleNames) {
247 dmSrcCaller.pkgName = bundleName;
248 HILOGI("dmSrcCaller networkId %{public}s, accountId %{public}s, userId %{public}s, pkgName %{public}s; "
249 "dmDstCallee networkId %{public}s.", GetAnonymStr(dmSrcCaller.networkId).c_str(),
250 GetAnonymStr(dmSrcCaller.accountId).c_str(), GetAnonymInt32(dmSrcCaller.userId).c_str(),
251 dmSrcCaller.pkgName.c_str(), GetAnonymStr(dmDstCallee.networkId).c_str());
252 if (!DeviceManager::GetInstance().CheckIsSameAccount(dmSrcCaller, dmDstCallee)) {
253 continue;
254 }
255 return true;
256 }
257 return false;
258 #else // DMSFWK_SAME_ACCOUNT
259 HILOGI("Not support remote same account check.");
260 return false;
261 #endif // DMSFWK_SAME_ACCOUNT
262 }
263
CheckAclList(const std::string & dstNetworkId,const AccountInfo & dmsAccountInfo,const CallerInfo & callerInfo,const std::string & targetBundleName)264 bool DistributedSchedPermission::CheckAclList(const std::string& dstNetworkId, const AccountInfo& dmsAccountInfo,
265 const CallerInfo& callerInfo, const std::string& targetBundleName)
266 {
267 DmAccessCaller dmSrcCaller = {
268 .accountId = dmsAccountInfo.activeAccountId,
269 .networkId = callerInfo.sourceDeviceId,
270 .userId = dmsAccountInfo.userId,
271 .tokenId = callerInfo.accessToken,
272 };
273 DmAccessCallee dmDstCallee = {
274 .networkId = dstNetworkId,
275 .peerId = "",
276 };
277 std::string localNetworkId;
278 if (!DtbschedmgrDeviceInfoStorage::GetInstance().GetLocalDeviceId(localNetworkId)) {
279 HILOGE("GetLocalDeviceId failed");
280 return false;
281 }
282 #ifdef OS_ACCOUNT_PART
283 if (dstNetworkId == localNetworkId) {
284 AccountInfo dstAccountInfo;
285 if (!GetOsAccountData(dstAccountInfo)) {
286 HILOGE("Get Os accountId and userId fail.");
287 }
288 dmDstCallee.accountId = dstAccountInfo.activeAccountId;
289 dmDstCallee.userId = dstAccountInfo.userId;
290 dmDstCallee.tokenId = AccessToken::AccessTokenKit::GetHapTokenID(dmDstCallee.userId, targetBundleName, 0);
291 HILOGI("calleeAccountId: %{public}s, callerUserId: %{public}d",
292 GetAnonymStr(dmDstCallee.accountId).c_str(), dmDstCallee.userId);
293 }
294 #endif
295 HILOGI("dmSrcCaller networkId %{public}s, accountId %{public}s, userId %{public}s",
296 GetAnonymStr(dmSrcCaller.networkId).c_str(), GetAnonymStr(dmSrcCaller.accountId).c_str(),
297 GetAnonymInt32(dmSrcCaller.userId).c_str());
298 for (const auto& bundleName : callerInfo.bundleNames) {
299 dmSrcCaller.pkgName = bundleName;
300 HILOGI("pkgName: %{public}s.", dmSrcCaller.pkgName.c_str());
301 if (!DeviceManager::GetInstance().CheckAccessControl(dmSrcCaller, dmDstCallee)) {
302 continue;
303 }
304 return true;
305 }
306 dmSrcCaller.pkgName = targetBundleName;
307 HILOGI("targetBundleName: %{public}s.", dmSrcCaller.pkgName.c_str());
308 if (DeviceManager::GetInstance().CheckAccessControl(dmSrcCaller, dmDstCallee)) {
309 return true;
310 }
311 return false;
312 }
313
GetRelatedGroups(const std::string & udid,const std::vector<std::string> & bundleNames,AccountInfo & accountInfo)314 bool DistributedSchedPermission::GetRelatedGroups(const std::string& udid,
315 const std::vector<std::string>& bundleNames, AccountInfo& accountInfo)
316 {
317 for (const auto& bundleName : bundleNames) {
318 std::string returnGroups;
319 if (!DistributedSchedAdapter::GetInstance().GetRelatedGroups(udid, bundleName, returnGroups)) {
320 continue;
321 }
322 std::vector<GroupInfo> groupInfos;
323 if (!ParseGroupInfos(returnGroups, groupInfos)) {
324 continue;
325 }
326 for (const auto& groupInfo : groupInfos) {
327 // check group type is whether (same count or point to point) or not
328 if (groupInfo.groupType != GroupType::IDENTICAL_ACCOUNT_GROUP
329 && groupInfo.groupType != GroupType::PEER_TO_PEER_GROUP) {
330 continue;
331 }
332 accountInfo.groupIdList.push_back(groupInfo.groupId);
333 if (groupInfo.groupType == GroupType::IDENTICAL_ACCOUNT_GROUP
334 && accountInfo.accountType != IDistributedSched::SAME_ACCOUNT_TYPE) {
335 accountInfo.accountType = IDistributedSched::SAME_ACCOUNT_TYPE;
336 }
337 }
338 }
339 if (accountInfo.groupIdList.empty()) {
340 HILOGE("groupIdList is empty");
341 return false;
342 }
343 return true;
344 }
345
ParseGroupInfos(const std::string & returnGroupStr,std::vector<GroupInfo> & groupInfos)346 bool DistributedSchedPermission::ParseGroupInfos(const std::string& returnGroupStr, std::vector<GroupInfo>& groupInfos)
347 {
348 nlohmann::json groupInfoJson = nlohmann::json::parse(returnGroupStr, nullptr, false);
349 if (groupInfoJson.is_discarded()) {
350 HILOGE("returnGroupStr parse failed");
351 return false;
352 }
353 HILOGD("groupInfoJson:%{public}s", groupInfoJson.dump().c_str());
354 groupInfos = groupInfoJson.get<std::vector<GroupInfo>>();
355 if (groupInfos.empty()) {
356 HILOGE("groupInfos is empty");
357 return false;
358 }
359 return true;
360 }
361
GetTargetAbility(const AAFwk::Want & want,AppExecFwk::AbilityInfo & targetAbility,bool needQueryExtension) const362 bool DistributedSchedPermission::GetTargetAbility(const AAFwk::Want& want,
363 AppExecFwk::AbilityInfo& targetAbility, bool needQueryExtension) const
364 {
365 if (BundleManagerInternal::QueryAbilityInfo(want, targetAbility)) {
366 if (want.GetIntParam(DMS_MISSION_ID, DEFAULT_DMS_MISSION_ID) != DEFAULT_DMS_MISSION_ID &&
367 (targetAbility.type == AppExecFwk::AbilityType::SERVICE ||
368 targetAbility.type == AppExecFwk::AbilityType::EXTENSION)) {
369 HILOGE("StartAbilityForResult can not start service and extension ability");
370 return false;
371 }
372 return true;
373 }
374 if (needQueryExtension) {
375 HILOGI("QueryAbilityInfo failed, try to QueryExtensionAbilityInfo");
376 // try to find extension
377 AppExecFwk::ExtensionAbilityInfo extensionAbility;
378 if (BundleManagerInternal::QueryExtensionAbilityInfo(want, extensionAbility)) {
379 // extensionAbilityInfo translates to abilityInfo
380 BundleManagerInternal::InitAbilityInfoFromExtension(extensionAbility, targetAbility);
381 return true;
382 }
383 }
384 HILOGE("QueryAbilityInfo failed, want bundle name=%{public}s, ability name=%{public}s.",
385 want.GetElement().GetBundleName().c_str(), want.GetElement().GetAbilityName().c_str());
386 return false;
387 }
388
CheckGetCallerPermission(const AAFwk::Want & want,const CallerInfo & callerInfo,const AccountInfo & accountInfo,AppExecFwk::AbilityInfo & targetAbility)389 int32_t DistributedSchedPermission::CheckGetCallerPermission(const AAFwk::Want& want, const CallerInfo& callerInfo,
390 const AccountInfo& accountInfo, AppExecFwk::AbilityInfo& targetAbility)
391 {
392 // 1.check account access permission in no account networking environment.
393 if (!CheckAccountAccessPermission(callerInfo, accountInfo, targetAbility.bundleName)) {
394 HILOGE("CheckAccountAccessPermission denied or failed!");
395 return DMS_ACCOUNT_ACCESS_PERMISSION_DENIED;
396 }
397 // 2. check call with same appid
398 if (!BundleManagerInternal::IsSameAppId(callerInfo.callerAppId, targetAbility.bundleName)) {
399 HILOGE("the appId is different, check permission denied!");
400 return CALL_PERMISSION_DENIED;
401 }
402 // 3. check background permission
403 if (!CheckBackgroundPermission(targetAbility, callerInfo, want, false)) {
404 HILOGE("Check background permission failed!");
405 return DMS_BACKGROUND_PERMISSION_DENIED;
406 }
407 // 4. check device security level
408 if (!targetAbility.visible &&
409 !CheckDeviceSecurityLevel(callerInfo.sourceDeviceId, want.GetElement().GetDeviceID())) {
410 HILOGE("check device security level failed!");
411 return CALL_PERMISSION_DENIED;
412 }
413 HILOGI("CheckGetCallerPermission success!!");
414 return ERR_OK;
415 }
416
IsFoundationCall() const417 bool DistributedSchedPermission::IsFoundationCall() const
418 {
419 uint32_t accessToken = IPCSkeleton::GetCallingTokenID();
420 AccessToken::NativeTokenInfo nativeTokenInfo;
421 int32_t result = AccessToken::AccessTokenKit::GetNativeTokenInfo(accessToken, nativeTokenInfo);
422 if (result == ERR_OK && nativeTokenInfo.processName == FOUNDATION_PROCESS_NAME) {
423 return true;
424 }
425 HILOGE("not foundation called, processName:%{private}s", nativeTokenInfo.processName.c_str());
426 return false;
427 }
428
IsSceneBoardCall() const429 bool DistributedSchedPermission::IsSceneBoardCall() const
430 {
431 int32_t activeAccountId = 0;
432 #ifdef OS_ACCOUNT_PART
433 std::vector<int32_t> ids;
434 int32_t errCode = AccountSA::OsAccountManager::QueryActiveOsAccountIds(ids);
435 if (errCode != ERR_OK || ids.empty()) {
436 HILOGE("QueryActiveOsAccountIds failed.");
437 return false;
438 }
439 activeAccountId = ids[0];
440 #endif
441 AppExecFwk::ApplicationInfo appInfo;
442 if (BundleManagerInternal::GetApplicationInfoFromBms(BUNDLE_NAME_SCENEBOARD,
443 AppExecFwk::BundleFlag::GET_BUNDLE_DEFAULT, activeAccountId, appInfo) != ERR_OK) {
444 HILOGE("get applicationInfo failed.");
445 return false;
446 }
447 auto accessTokenId = IPCSkeleton::GetCallingTokenID();
448 if (accessTokenId != appInfo.accessTokenId) {
449 HILOGE("not sceneBoard called.");
450 return false;
451 }
452 return true;
453 }
454
CheckPermission(uint32_t accessToken,const std::string & permissionName) const455 int32_t DistributedSchedPermission::CheckPermission(uint32_t accessToken, const std::string& permissionName) const
456 {
457 HILOGI("CheckPermission called.");
458 if (VerifyPermission(accessToken, permissionName)) {
459 return ERR_OK;
460 }
461 return DMS_PERMISSION_DENIED;
462 }
463
CheckPermissionAll(uint32_t accessToken,const std::string & permissionName) const464 int32_t DistributedSchedPermission::CheckPermissionAll(uint32_t accessToken, const std::string& permissionName) const
465 {
466 HILOGI("CheckPermissionAll called.");
467 if (VerifyPermission(accessToken, permissionName)) {
468 return ERR_OK;
469 }
470 return DMS_PERMISSION_DENIED;
471 }
472
MarkUriPermission(OHOS::AAFwk::Want & want,uint32_t accessToken)473 void DistributedSchedPermission::MarkUriPermission(OHOS::AAFwk::Want& want, uint32_t accessToken)
474 {
475 if ((want.GetFlags() & (Want::FLAG_AUTH_READ_URI_PERMISSION | Want::FLAG_AUTH_WRITE_URI_PERMISSION)) == 0) {
476 return;
477 }
478 auto bms = BundleManagerInternal::GetBundleManager();
479 if (bms == nullptr) {
480 HILOGW("Failed to get bms.");
481 return;
482 }
483 std::vector<std::string> uriVec = want.GetStringArrayParam(PARAMS_STREAM);
484 std::string uriStr = want.GetUri().ToString();
485 uriVec.emplace_back(uriStr);
486 std::vector<std::string> uriVecPermission;
487 HILOGI("GrantUriPermission uriVec size: %{public}zu", uriVec.size());
488 for (std::string str : uriVec) {
489 Uri uri(str);
490 if (!IsDistributedFile(uri.GetPath())) {
491 continue;
492 }
493 std::string authority = uri.GetAuthority();
494 HILOGI("uri authority is %{public}s.", authority.c_str());
495 AppExecFwk::BundleInfo bundleInfo;
496 int32_t activeAccountId = 0;
497 #ifdef OS_ACCOUNT_PART
498 std::vector<int32_t> ids;
499 int32_t errCode = AccountSA::OsAccountManager::QueryActiveOsAccountIds(ids);
500 if (errCode != ERR_OK || ids.empty()) {
501 return;
502 }
503 activeAccountId = ids[0];
504 #endif
505 if (!bms->GetBundleInfo(authority,
506 AppExecFwk::BundleFlag::GET_BUNDLE_WITH_EXTENSION_INFO, bundleInfo, activeAccountId)) {
507 HILOGW("To fail to get bundle info according to uri.");
508 continue;
509 }
510 if (bundleInfo.applicationInfo.accessTokenId == accessToken) {
511 HILOGI("uri token is true.");
512 uriVecPermission.emplace_back(str);
513 }
514 }
515 want.SetParam(PARAMS_URI, uriVecPermission);
516 }
517
IsDistributedFile(const std::string & path) const518 bool DistributedSchedPermission::IsDistributedFile(const std::string& path) const
519 {
520 if (path.compare(0, DISTRIBUTED_FILES_PATH.size(), DISTRIBUTED_FILES_PATH) == 0) {
521 return true;
522 }
523 HILOGE("uri path is false.");
524 return false;
525 }
526
VerifyPermission(uint32_t accessToken,const std::string & permissionName) const527 bool DistributedSchedPermission::VerifyPermission(uint32_t accessToken, const std::string& permissionName) const
528 {
529 int32_t result = AccessToken::AccessTokenKit::VerifyAccessToken(accessToken, permissionName);
530 if (result == AccessToken::PermissionState::PERMISSION_DENIED) {
531 HILOGE("permission denied, permissionName:%{public}s", permissionName.c_str());
532 return false;
533 }
534 HILOGD("permission matched.");
535 return true;
536 }
537
CheckAccountAccessPermission(const CallerInfo & callerInfo,const AccountInfo & accountInfo,const std::string & targetBundleName,bool isNewCollab)538 bool DistributedSchedPermission::CheckAccountAccessPermission(const CallerInfo& callerInfo,
539 const AccountInfo& accountInfo, const std::string& targetBundleName, bool isNewCollab)
540 {
541 std::string udid = DnetworkAdapter::GetInstance()->GetUdidByNetworkId(callerInfo.sourceDeviceId);
542 std::string dstNetworkId;
543 if (!DtbschedmgrDeviceInfoStorage::GetInstance().GetLocalDeviceId(dstNetworkId)) {
544 HILOGE("GetLocalDeviceId failed");
545 return false;
546 }
547
548 #ifdef DMSFWK_SAME_ACCOUNT
549 if (CheckDstSameAccount(dstNetworkId, accountInfo, callerInfo)) {
550 return true;
551 }
552 if (isNewCollab && !BundleManagerInternal::IsSameAppId(callerInfo.callerAppId, targetBundleName)) {
553 HILOGE("the appId isn't the same, check new collab start control permission fail.");
554 return false;
555 }
556 HILOGI("check same account by DM fail, will try check access Group by hichain");
557 #endif
558
559 if (DistributedSchedAdapter::GetInstance().CheckAccessToGroup(udid, targetBundleName)) {
560 return true;
561 }
562
563 HILOGI("Check access Group by hichain fail, will try check different account ACL by DM.");
564 if (CheckAclList(dstNetworkId, accountInfo, callerInfo, targetBundleName)) {
565 return true;
566 }
567
568 HILOGE("Check different account ACL by DM fail.");
569 return false;
570 }
571
CheckComponentAccessPermission(const AppExecFwk::AbilityInfo & targetAbility,const CallerInfo & callerInfo,const AccountInfo & accountInfo,const AAFwk::Want & want) const572 bool DistributedSchedPermission::CheckComponentAccessPermission(const AppExecFwk::AbilityInfo& targetAbility,
573 const CallerInfo& callerInfo, const AccountInfo& accountInfo, const AAFwk::Want& want) const
574 {
575 // reject directly when in no account networking environment and target ability is not visible,
576 if (!targetAbility.visible) {
577 HILOGE("target ability is not visible, permission denied!");
578 return false;
579 }
580 HILOGD("check component permission success");
581 return true;
582 }
583
CheckMigrateStartCtrlPer(const AppExecFwk::AbilityInfo & targetAbility,const CallerInfo & callerInfo,const AAFwk::Want & want,bool isSameBundle)584 bool DistributedSchedPermission::CheckMigrateStartCtrlPer(const AppExecFwk::AbilityInfo& targetAbility,
585 const CallerInfo& callerInfo, const AAFwk::Want& want, bool isSameBundle)
586 {
587 std::string bundleName = want.GetBundle();
588 // check if continuation with same appid
589 HILOGI("Check migration start control permission with same appid enter.");
590 if (!isSameBundle) {
591 return true;
592 }
593 if (BundleManagerInternal::IsSameAppId(callerInfo.callerAppId, targetAbility.bundleName)) {
594 HILOGD("the appId is the same, check migration start control permission success!");
595 return true;
596 }
597 HILOGE("the appId is different in the migration scenario, permission denied!");
598 return false;
599 }
600
CheckCollaborateStartCtrlPer(const AppExecFwk::AbilityInfo & targetAbility,const CallerInfo & callerInfo,const AAFwk::Want & want) const601 bool DistributedSchedPermission::CheckCollaborateStartCtrlPer(const AppExecFwk::AbilityInfo& targetAbility,
602 const CallerInfo& callerInfo, const AAFwk::Want& want) const
603 {
604 HILOGI("Check collaboration start control permission enter.");
605 // 1. check background permission
606 if (!CheckBackgroundPermission(targetAbility, callerInfo, want, true)) {
607 HILOGE("Check background permission failed!");
608 return false;
609 }
610 // 2. check device security level
611 if (!targetAbility.visible &&
612 !CheckDeviceSecurityLevel(callerInfo.sourceDeviceId, want.GetElement().GetDeviceID())) {
613 HILOGE("check device security level failed!");
614 return false;
615 }
616 // 3. check start or connect ability with same appid
617 if (BundleManagerInternal::IsSameAppId(callerInfo.callerAppId, targetAbility.bundleName)) {
618 HILOGD("the appId is the same, check permission success!");
619 return true;
620 }
621 // 4. check if target ability is not visible and without PERMISSION_START_INVISIBLE_ABILITY
622 if (!CheckTargetAbilityVisible(targetAbility, callerInfo)) {
623 HILOGE("target ability is not visible and has no PERMISSION_START_INVISIBLE_ABILITY, permission denied!");
624 return false;
625 }
626 // 5. check if service of fa mode can associatedWakeUp
627 if (!targetAbility.isStageBasedModel && targetAbility.type == AppExecFwk::AbilityType::SERVICE &&
628 !targetAbility.applicationInfo.associatedWakeUp) {
629 HILOGE("target ability is service ability(FA) and associatedWakeUp is false, permission denied!");
630 return false;
631 }
632 HILOGD("Check collaboration start control permission success");
633 return true;
634 }
635
CheckCollabStartControlPermission(const AppExecFwk::AbilityInfo & targetAbility,const CallerInfo & callerInfo,const AAFwk::Want & want)636 bool DistributedSchedPermission::CheckCollabStartControlPermission(const AppExecFwk::AbilityInfo& targetAbility,
637 const CallerInfo& callerInfo, const AAFwk::Want& want)
638 {
639 HILOGI("Check new collaboration start control permission enter.");
640 // 1. check background permission
641 if (!CheckBackgroundPermission(targetAbility, callerInfo, want, true)) {
642 HILOGE("Check background permission failed!");
643 return false;
644 }
645 // 2. check device security level
646 if (!targetAbility.visible &&
647 !CheckDeviceSecurityLevel(callerInfo.sourceDeviceId, want.GetElement().GetDeviceID())) {
648 HILOGE("check device security level failed!");
649 return false;
650 }
651 // 3. check start or connect ability with same appid
652 if (BundleManagerInternal::IsSameAppId(callerInfo.callerAppId, targetAbility.bundleName)) {
653 HILOGD("the appId is the same, check permission success!");
654 return true;
655 }
656 // 4. check if target ability is not visible and without PERMISSION_START_INVISIBLE_ABILITY
657 if (!CheckTargetAbilityVisible(targetAbility, callerInfo)) {
658 HILOGE("target ability is not visible and has no PERMISSION_START_INVISIBLE_ABILITY, permission denied!");
659 return false;
660 }
661 // 5. check if service of fa mode can associatedWakeUp
662 if (!targetAbility.isStageBasedModel && targetAbility.type == AppExecFwk::AbilityType::SERVICE &&
663 !targetAbility.applicationInfo.associatedWakeUp) {
664 HILOGE("target ability is service ability(FA) and associatedWakeUp is false, permission denied!");
665 return false;
666 }
667 HILOGD("Check collaboration start control permission success");
668 return true;
669 }
670
CheckBackgroundPermission(const AppExecFwk::AbilityInfo & targetAbility,const CallerInfo & callerInfo,const AAFwk::Want & want,bool needCheckApiVersion) const671 bool DistributedSchedPermission::CheckBackgroundPermission(const AppExecFwk::AbilityInfo& targetAbility,
672 const CallerInfo& callerInfo, const AAFwk::Want& want, bool needCheckApiVersion) const
673 {
674 if (callerInfo.extraInfoJson.empty() ||
675 callerInfo.extraInfoJson.find(DMS_VERSION_ID) == callerInfo.extraInfoJson.end()) {
676 HILOGD("the version is low");
677 return true;
678 }
679 AAFwk::Want* remoteWant = const_cast<Want*>(&want);
680 bool isCallerBackGround = remoteWant->GetBoolParam(DMS_IS_CALLER_BACKGROUND, true);
681 remoteWant->RemoveParam(DMS_IS_CALLER_BACKGROUND);
682 if (!isCallerBackGround) {
683 HILOGD("the app is foreground");
684 return true;
685 }
686 int apiVersion = remoteWant->GetIntParam(DMS_API_VERSION, DEFAULT_DMS_API_VERSION);
687 remoteWant->RemoveParam(DMS_API_VERSION);
688 // service in fa mode(API 8) do not need check
689 if (needCheckApiVersion && CheckMinApiVersion(targetAbility, apiVersion)) {
690 HILOGD("the app is service ability of fa mode and is under api 8");
691 return true;
692 }
693 uint32_t dAccessToken = AccessToken::AccessTokenKit::AllocLocalTokenID(callerInfo.sourceDeviceId,
694 callerInfo.accessToken);
695 if (dAccessToken == 0) {
696 HILOGE("dAccessTokenID is invalid!");
697 return false;
698 }
699 // check if background's ability has PERMISSION_START_ABILITIES_FROM_BACKGROUND
700 if (CheckPermission(dAccessToken, PERMISSION_START_ABILITIES_FROM_BACKGROUND) == ERR_OK ||
701 CheckPermission(dAccessToken, PERMISSION_START_ABILIIES_FROM_BACKGROUND) == ERR_OK) {
702 HILOGD("the app has PERMISSION_START_ABILITIES_FROM_BACKGROUND");
703 return true;
704 }
705 HILOGE("CheckBackgroundPermission failed!");
706 return false;
707 }
708
CheckMinApiVersion(const AppExecFwk::AbilityInfo & targetAbility,int32_t apiVersion) const709 bool DistributedSchedPermission::CheckMinApiVersion(const AppExecFwk::AbilityInfo& targetAbility,
710 int32_t apiVersion) const
711 {
712 if (!targetAbility.isStageBasedModel && targetAbility.type == AppExecFwk::AbilityType::SERVICE &&
713 apiVersion <= FA_MODULE_ALLOW_MIN_API_VERSION) {
714 HILOGD("CheckMinApiVersion pass");
715 return true;
716 }
717 return false;
718 }
719
CheckDeviceSecurityLevel(const std::string & srcDeviceId,const std::string & dstDeviceId) const720 bool DistributedSchedPermission::CheckDeviceSecurityLevel(const std::string& srcDeviceId,
721 const std::string& dstDeviceId) const
722 {
723 std::string srcUdid = DnetworkAdapter::GetInstance()->GetUdidByNetworkId(srcDeviceId);
724 if (srcUdid.empty()) {
725 HILOGE("src udid is empty");
726 return false;
727 }
728 std::string dstUdid = DnetworkAdapter::GetInstance()->GetUdidByNetworkId(dstDeviceId);
729 if (dstUdid.empty()) {
730 HILOGE("dst udid is empty");
731 return false;
732 }
733 int32_t srcDeviceSecurityLevel = GetDeviceSecurityLevel(srcUdid);
734 int32_t dstDeviceSecurityLevel = GetDeviceSecurityLevel(dstUdid);
735 if (srcDeviceSecurityLevel == DEFAULT_DEVICE_SECURITY_LEVEL ||
736 srcDeviceSecurityLevel < dstDeviceSecurityLevel) {
737 HILOGE("the device security of source device is lower");
738 return false;
739 }
740 return true;
741 }
742
GetDeviceSecurityLevel(const std::string & udid) const743 int32_t DistributedSchedPermission::GetDeviceSecurityLevel(const std::string& udid) const
744 {
745 DeviceIdentify devIdentify;
746 devIdentify.length = DEVICE_ID_MAX_LEN;
747 int32_t ret = memcpy_s(devIdentify.identity, DEVICE_ID_MAX_LEN, udid.c_str(), udid.length());
748 if (ret != 0) {
749 HILOGE("str copy failed %{public}d", ret);
750 return DEFAULT_DEVICE_SECURITY_LEVEL;
751 }
752 DeviceSecurityInfo *info = nullptr;
753 ret = RequestDeviceSecurityInfo(&devIdentify, nullptr, &info);
754 if (ret != SUCCESS) {
755 HILOGE("request device security info failed %{public}d", ret);
756 FreeDeviceSecurityInfo(info);
757 info = nullptr;
758 return DEFAULT_DEVICE_SECURITY_LEVEL;
759 }
760 int32_t level = 0;
761 ret = GetDeviceSecurityLevelValue(info, &level);
762 HILOGD("get device security level, level is %{public}d", level);
763 FreeDeviceSecurityInfo(info);
764 info = nullptr;
765 if (ret != SUCCESS) {
766 HILOGE("get device security level failed %{public}d", ret);
767 return DEFAULT_DEVICE_SECURITY_LEVEL;
768 }
769 return level;
770 }
771
CheckTargetAbilityVisible(const AppExecFwk::AbilityInfo & targetAbility,const CallerInfo & callerInfo) const772 bool DistributedSchedPermission::CheckTargetAbilityVisible(const AppExecFwk::AbilityInfo& targetAbility,
773 const CallerInfo& callerInfo) const
774 {
775 if (targetAbility.visible) {
776 HILOGD("Target ability is visible.");
777 return true;
778 }
779 uint32_t dAccessToken = AccessToken::AccessTokenKit::AllocLocalTokenID(callerInfo.sourceDeviceId,
780 callerInfo.accessToken);
781 if (dAccessToken == 0) {
782 HILOGE("dAccessTokenID is invalid!");
783 return false;
784 }
785 if (CheckPermissionAll(dAccessToken, PERMISSION_START_INVISIBLE_ABILITY) != ERR_OK) {
786 HILOGE("CheckTargetAbilityVisible failed.");
787 return false;
788 }
789 HILOGD("CheckTargetAbilityVisible passed.");
790 return true;
791 }
792
RemoveRemoteObjectFromWant(std::shared_ptr<AAFwk::Want> want) const793 void DistributedSchedPermission::RemoveRemoteObjectFromWant(std::shared_ptr<AAFwk::Want> want) const
794 {
795 if (want == nullptr) {
796 return;
797 }
798 WantParams wantParams = want->GetParams();
799 std::map<std::string, sptr<IInterface>> params = wantParams.GetParams();
800 for (auto param : params) {
801 sptr<IInterface> object = param.second;
802 IWantParams *wp = IWantParams::Query(object);
803 if (wp == nullptr) {
804 continue;
805 }
806 WantParams value = WantParamWrapper::Unbox(wp);
807 auto type = value.GetParam(TYPE_PROPERTY);
808 AAFwk::IString *typeP = AAFwk::IString::Query(type);
809 if (typeP == nullptr) {
810 continue;
811 }
812 std::string typeValue = AAFwk::String::Unbox(typeP);
813 if (typeValue == REMOTE_OBJECT) {
814 wantParams.Remove(param.first);
815 }
816 }
817 want->SetParams(wantParams);
818 }
819 }
820 }
821