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
GetAccountInfo(const std::string & remoteNetworkId,const CallerInfo & callerInfo,AccountInfo & accountInfo)144 int32_t DistributedSchedPermission::GetAccountInfo(const std::string& remoteNetworkId,
145 const CallerInfo& callerInfo, AccountInfo& accountInfo)
146 {
147 if (remoteNetworkId.empty()) {
148 HILOGE("remoteNetworkId is empty");
149 return ERR_NULL_OBJECT;
150 }
151 std::string udid = DnetworkAdapter::GetInstance()->GetUdidByNetworkId(remoteNetworkId);
152 if (udid.empty()) {
153 HILOGE("udid is empty");
154 return ERR_NULL_OBJECT;
155 }
156 if (!GetOsAccountData(accountInfo)) {
157 HILOGE("Get Os accountId and userId fail.");
158 return INVALID_PARAMETERS_ERR;
159 }
160
161 #ifdef DMSFWK_SAME_ACCOUNT
162 if (CheckDstSameAccount(remoteNetworkId, accountInfo, callerInfo)) {
163 return ERR_OK;
164 }
165 HILOGI("check same account by DM fail, will try check access Group by hichain");
166 #endif // DMSFWK_SAME_ACCOUNT
167
168 if (GetRelatedGroups(udid, callerInfo.bundleNames, accountInfo)) {
169 return ERR_OK;
170 }
171
172 HILOGI("Check access Group by hichain fail, will try check different account ACL by DM.");
173 if (CheckAclList(remoteNetworkId, accountInfo, callerInfo)) {
174 return ERR_OK;
175 }
176 HILOGE("Check different account ACL list by DM fail.");
177 return INVALID_PARAMETERS_ERR;
178 }
179
GetOsAccountData(AccountInfo & dmsAccountInfo)180 bool DistributedSchedPermission::GetOsAccountData(AccountInfo& dmsAccountInfo)
181 {
182 #ifdef OS_ACCOUNT_PART
183 std::vector<int32_t> ids;
184 ErrCode ret = AccountSA::OsAccountManager::QueryActiveOsAccountIds(ids);
185 if (ret != ERR_OK || ids.empty()) {
186 HILOGE("Get userId from active Os AccountIds fail, ret : %{public}d", ret);
187 return false;
188 }
189 dmsAccountInfo.userId = ids[0];
190
191 AccountSA::OhosAccountInfo osAccountInfo;
192 ret = AccountSA::OhosAccountKits::GetInstance().GetOhosAccountInfo(osAccountInfo);
193 if (ret != 0 || osAccountInfo.uid_ == "") {
194 HILOGE("Get accountId from Ohos account info fail, ret: %{public}d.", ret);
195 return false;
196 }
197 dmsAccountInfo.activeAccountId = osAccountInfo.uid_;
198 HILOGI("Get caller dmsAccountInfo OK, accountId %{public}s, userId %{public}s.",
199 GetAnonymStr(dmsAccountInfo.activeAccountId).c_str(), GetAnonymInt32(dmsAccountInfo.userId).c_str());
200 #endif
201 return true;
202 }
203
CheckDstSameAccount(const std::string & dstNetworkId,const AccountInfo & dmsAccountInfo,const CallerInfo & callerInfo)204 bool DistributedSchedPermission::CheckDstSameAccount(const std::string& dstNetworkId,
205 const AccountInfo& dmsAccountInfo, const CallerInfo& callerInfo)
206 {
207 #ifdef DMSFWK_SAME_ACCOUNT
208 DmAccessCaller dmSrcCaller = {
209 .accountId = dmsAccountInfo.activeAccountId,
210 .networkId = callerInfo.sourceDeviceId,
211 .userId = dmsAccountInfo.userId,
212 .tokenId = callerInfo.accessToken,
213 };
214 DmAccessCallee dmDstCallee = {
215 .networkId = dstNetworkId,
216 .peerId = "",
217 };
218 for (const auto& bundleName : callerInfo.bundleNames) {
219 dmSrcCaller.pkgName = bundleName;
220 HILOGI("dmSrcCaller networkId %{public}s, accountId %{public}s, userId %{public}s, pkgName %{public}s; "
221 "dmDstCallee networkId %{public}s.", GetAnonymStr(dmSrcCaller.networkId).c_str(),
222 GetAnonymStr(dmSrcCaller.accountId).c_str(), GetAnonymInt32(dmSrcCaller.userId).c_str(),
223 dmSrcCaller.pkgName.c_str(), GetAnonymStr(dmDstCallee.networkId).c_str());
224 if (!DeviceManager::GetInstance().CheckIsSameAccount(dmSrcCaller, dmDstCallee)) {
225 continue;
226 }
227 return true;
228 }
229 return false;
230 #else // DMSFWK_SAME_ACCOUNT
231 HILOGI("Not support remote same account check.");
232 return false;
233 #endif // DMSFWK_SAME_ACCOUNT
234 }
235
CheckAclList(const std::string & dstNetworkId,const AccountInfo & dmsAccountInfo,const CallerInfo & callerInfo)236 bool DistributedSchedPermission::CheckAclList(const std::string& dstNetworkId,
237 const AccountInfo& dmsAccountInfo, const CallerInfo& callerInfo)
238 {
239 DmAccessCaller dmSrcCaller = {
240 .accountId = dmsAccountInfo.activeAccountId,
241 .networkId = callerInfo.sourceDeviceId,
242 .userId = dmsAccountInfo.userId,
243 .tokenId = callerInfo.accessToken,
244 };
245 DmAccessCallee dmDstCallee = {
246 .networkId = dstNetworkId,
247 .peerId = "",
248 };
249 for (const auto& bundleName : callerInfo.bundleNames) {
250 dmSrcCaller.pkgName = bundleName;
251 HILOGI("dmSrcCaller networkId %{public}s, accountId %{public}s, userId %{public}s, pkgName %{public}s; "
252 "dmDstCallee networkId %{public}s.", GetAnonymStr(dmSrcCaller.networkId).c_str(),
253 GetAnonymStr(dmSrcCaller.accountId).c_str(), GetAnonymInt32(dmSrcCaller.userId).c_str(),
254 dmSrcCaller.pkgName.c_str(), GetAnonymStr(dmDstCallee.networkId).c_str());
255 if (!DeviceManager::GetInstance().CheckAccessControl(dmSrcCaller, dmDstCallee)) {
256 continue;
257 }
258 return true;
259 }
260 return false;
261 }
262
GetRelatedGroups(const std::string & udid,const std::vector<std::string> & bundleNames,AccountInfo & accountInfo)263 bool DistributedSchedPermission::GetRelatedGroups(const std::string& udid,
264 const std::vector<std::string>& bundleNames, AccountInfo& accountInfo)
265 {
266 for (const auto& bundleName : bundleNames) {
267 std::string returnGroups;
268 if (!DistributedSchedAdapter::GetInstance().GetRelatedGroups(udid, bundleName, returnGroups)) {
269 continue;
270 }
271 std::vector<GroupInfo> groupInfos;
272 if (!ParseGroupInfos(returnGroups, groupInfos)) {
273 continue;
274 }
275 for (const auto& groupInfo : groupInfos) {
276 // check group type is whether (same count or point to point) or not
277 if (groupInfo.groupType != GroupType::IDENTICAL_ACCOUNT_GROUP
278 && groupInfo.groupType != GroupType::PEER_TO_PEER_GROUP) {
279 continue;
280 }
281 accountInfo.groupIdList.push_back(groupInfo.groupId);
282 if (groupInfo.groupType == GroupType::IDENTICAL_ACCOUNT_GROUP
283 && accountInfo.accountType != IDistributedSched::SAME_ACCOUNT_TYPE) {
284 accountInfo.accountType = IDistributedSched::SAME_ACCOUNT_TYPE;
285 }
286 }
287 }
288 if (accountInfo.groupIdList.empty()) {
289 HILOGE("groupIdList is empty");
290 return false;
291 }
292 return true;
293 }
294
ParseGroupInfos(const std::string & returnGroupStr,std::vector<GroupInfo> & groupInfos)295 bool DistributedSchedPermission::ParseGroupInfos(const std::string& returnGroupStr, std::vector<GroupInfo>& groupInfos)
296 {
297 nlohmann::json groupInfoJson = nlohmann::json::parse(returnGroupStr, nullptr, false);
298 if (groupInfoJson.is_discarded()) {
299 HILOGE("returnGroupStr parse failed");
300 return false;
301 }
302 HILOGD("groupInfoJson:%{public}s", groupInfoJson.dump().c_str());
303 groupInfos = groupInfoJson.get<std::vector<GroupInfo>>();
304 if (groupInfos.empty()) {
305 HILOGE("groupInfos is empty");
306 return false;
307 }
308 return true;
309 }
310
GetTargetAbility(const AAFwk::Want & want,AppExecFwk::AbilityInfo & targetAbility,bool needQueryExtension) const311 bool DistributedSchedPermission::GetTargetAbility(const AAFwk::Want& want,
312 AppExecFwk::AbilityInfo& targetAbility, bool needQueryExtension) const
313 {
314 if (BundleManagerInternal::QueryAbilityInfo(want, targetAbility)) {
315 if (want.GetIntParam(DMS_MISSION_ID, DEFAULT_DMS_MISSION_ID) != DEFAULT_DMS_MISSION_ID &&
316 (targetAbility.type == AppExecFwk::AbilityType::SERVICE ||
317 targetAbility.type == AppExecFwk::AbilityType::EXTENSION)) {
318 HILOGE("StartAbilityForResult can not start service and extension ability");
319 return false;
320 }
321 return true;
322 }
323 if (needQueryExtension) {
324 HILOGI("QueryAbilityInfo failed, try to QueryExtensionAbilityInfo");
325 // try to find extension
326 AppExecFwk::ExtensionAbilityInfo extensionAbility;
327 if (BundleManagerInternal::QueryExtensionAbilityInfo(want, extensionAbility)) {
328 // extensionAbilityInfo translates to abilityInfo
329 BundleManagerInternal::InitAbilityInfoFromExtension(extensionAbility, targetAbility);
330 return true;
331 }
332 }
333 HILOGE("QueryAbilityInfo failed, want bundle name=%{public}s, ability name=%{public}s.",
334 want.GetElement().GetBundleName().c_str(), want.GetElement().GetAbilityName().c_str());
335 return false;
336 }
337
CheckGetCallerPermission(const AAFwk::Want & want,const CallerInfo & callerInfo,const AccountInfo & accountInfo,AppExecFwk::AbilityInfo & targetAbility)338 int32_t DistributedSchedPermission::CheckGetCallerPermission(const AAFwk::Want& want, const CallerInfo& callerInfo,
339 const AccountInfo& accountInfo, AppExecFwk::AbilityInfo& targetAbility)
340 {
341 // 1.check account access permission in no account networking environment.
342 if (!CheckAccountAccessPermission(callerInfo, accountInfo, targetAbility.bundleName)) {
343 HILOGE("CheckAccountAccessPermission denied or failed!");
344 return DMS_ACCOUNT_ACCESS_PERMISSION_DENIED;
345 }
346 // 2. check call with same appid
347 if (!BundleManagerInternal::IsSameAppId(callerInfo.callerAppId, targetAbility.bundleName)) {
348 HILOGE("the appId is different, check permission denied!");
349 return CALL_PERMISSION_DENIED;
350 }
351 // 3. check background permission
352 if (!CheckBackgroundPermission(targetAbility, callerInfo, want, false)) {
353 HILOGE("Check background permission failed!");
354 return DMS_BACKGROUND_PERMISSION_DENIED;
355 }
356 // 4. check device security level
357 if (!targetAbility.visible &&
358 !CheckDeviceSecurityLevel(callerInfo.sourceDeviceId, want.GetElement().GetDeviceID())) {
359 HILOGE("check device security level failed!");
360 return CALL_PERMISSION_DENIED;
361 }
362 HILOGI("CheckGetCallerPermission success!!");
363 return ERR_OK;
364 }
365
IsFoundationCall() const366 bool DistributedSchedPermission::IsFoundationCall() const
367 {
368 uint32_t accessToken = IPCSkeleton::GetCallingTokenID();
369 AccessToken::NativeTokenInfo nativeTokenInfo;
370 int32_t result = AccessToken::AccessTokenKit::GetNativeTokenInfo(accessToken, nativeTokenInfo);
371 if (result == ERR_OK && nativeTokenInfo.processName == FOUNDATION_PROCESS_NAME) {
372 return true;
373 }
374 HILOGE("not foundation called, processName:%{private}s", nativeTokenInfo.processName.c_str());
375 return false;
376 }
377
IsSceneBoardCall() const378 bool DistributedSchedPermission::IsSceneBoardCall() const
379 {
380 int32_t activeAccountId = 0;
381 #ifdef OS_ACCOUNT_PART
382 std::vector<int32_t> ids;
383 int32_t errCode = AccountSA::OsAccountManager::QueryActiveOsAccountIds(ids);
384 if (errCode != ERR_OK || ids.empty()) {
385 HILOGE("QueryActiveOsAccountIds failed.");
386 return false;
387 }
388 activeAccountId = ids[0];
389 #endif
390 AppExecFwk::ApplicationInfo appInfo;
391 if (BundleManagerInternal::GetApplicationInfoFromBms(BUNDLE_NAME_SCENEBOARD,
392 AppExecFwk::BundleFlag::GET_BUNDLE_DEFAULT, activeAccountId, appInfo) != ERR_OK) {
393 HILOGE("get applicationInfo failed.");
394 return false;
395 }
396 auto accessTokenId = IPCSkeleton::GetCallingTokenID();
397 if (accessTokenId != appInfo.accessTokenId) {
398 HILOGE("not sceneBoard called.");
399 return false;
400 }
401 return true;
402 }
403
CheckPermission(uint32_t accessToken,const std::string & permissionName) const404 int32_t DistributedSchedPermission::CheckPermission(uint32_t accessToken, const std::string& permissionName) const
405 {
406 HILOGI("CheckPermission called.");
407 if (VerifyPermission(accessToken, permissionName)) {
408 return ERR_OK;
409 }
410 return DMS_PERMISSION_DENIED;
411 }
412
CheckPermissionAll(uint32_t accessToken,const std::string & permissionName) const413 int32_t DistributedSchedPermission::CheckPermissionAll(uint32_t accessToken, const std::string& permissionName) const
414 {
415 HILOGI("CheckPermissionAll called.");
416 if (VerifyPermission(accessToken, permissionName)) {
417 return ERR_OK;
418 }
419 return DMS_PERMISSION_DENIED;
420 }
421
MarkUriPermission(OHOS::AAFwk::Want & want,uint32_t accessToken)422 void DistributedSchedPermission::MarkUriPermission(OHOS::AAFwk::Want& want, uint32_t accessToken)
423 {
424 if ((want.GetFlags() & (Want::FLAG_AUTH_READ_URI_PERMISSION | Want::FLAG_AUTH_WRITE_URI_PERMISSION)) == 0) {
425 return;
426 }
427 auto bms = BundleManagerInternal::GetBundleManager();
428 if (bms == nullptr) {
429 HILOGW("Failed to get bms.");
430 return;
431 }
432 std::vector<std::string> uriVec = want.GetStringArrayParam(PARAMS_STREAM);
433 std::string uriStr = want.GetUri().ToString();
434 uriVec.emplace_back(uriStr);
435 std::vector<std::string> uriVecPermission;
436 HILOGI("GrantUriPermission uriVec size: %{public}zu", uriVec.size());
437 for (std::string str : uriVec) {
438 Uri uri(str);
439 if (!IsDistributedFile(uri.GetPath())) {
440 continue;
441 }
442 std::string authority = uri.GetAuthority();
443 HILOGI("uri authority is %{public}s.", authority.c_str());
444 AppExecFwk::BundleInfo bundleInfo;
445 int32_t activeAccountId = 0;
446 #ifdef OS_ACCOUNT_PART
447 std::vector<int32_t> ids;
448 int32_t errCode = AccountSA::OsAccountManager::QueryActiveOsAccountIds(ids);
449 if (errCode != ERR_OK || ids.empty()) {
450 return;
451 }
452 activeAccountId = ids[0];
453 #endif
454 if (!bms->GetBundleInfo(authority,
455 AppExecFwk::BundleFlag::GET_BUNDLE_WITH_EXTENSION_INFO, bundleInfo, activeAccountId)) {
456 HILOGW("To fail to get bundle info according to uri.");
457 continue;
458 }
459 if (bundleInfo.applicationInfo.accessTokenId == accessToken) {
460 HILOGI("uri token is true.");
461 uriVecPermission.emplace_back(str);
462 }
463 }
464 want.SetParam(PARAMS_URI, uriVecPermission);
465 }
466
IsDistributedFile(const std::string & path) const467 bool DistributedSchedPermission::IsDistributedFile(const std::string& path) const
468 {
469 if (path.compare(0, DISTRIBUTED_FILES_PATH.size(), DISTRIBUTED_FILES_PATH) == 0) {
470 return true;
471 }
472 HILOGE("uri path is false.");
473 return false;
474 }
475
VerifyPermission(uint32_t accessToken,const std::string & permissionName) const476 bool DistributedSchedPermission::VerifyPermission(uint32_t accessToken, const std::string& permissionName) const
477 {
478 int32_t result = AccessToken::AccessTokenKit::VerifyAccessToken(accessToken, permissionName);
479 if (result == AccessToken::PermissionState::PERMISSION_DENIED) {
480 HILOGE("permission denied, permissionName:%{public}s", permissionName.c_str());
481 return false;
482 }
483 HILOGD("permission matched.");
484 return true;
485 }
486
CheckAccountAccessPermission(const CallerInfo & callerInfo,const AccountInfo & accountInfo,const std::string & targetBundleName)487 bool DistributedSchedPermission::CheckAccountAccessPermission(const CallerInfo& callerInfo,
488 const AccountInfo& accountInfo, const std::string& targetBundleName)
489 {
490 std::string udid = DnetworkAdapter::GetInstance()->GetUdidByNetworkId(callerInfo.sourceDeviceId);
491 std::string dstNetworkId;
492 if (!DtbschedmgrDeviceInfoStorage::GetInstance().GetLocalDeviceId(dstNetworkId)) {
493 HILOGE("GetLocalDeviceId failed");
494 return false;
495 }
496 DmAccessCaller dmSrcCaller = {
497 .accountId = accountInfo.activeAccountId,
498 .pkgName = targetBundleName,
499 .networkId = callerInfo.sourceDeviceId,
500 .userId = accountInfo.userId,
501 .tokenId = callerInfo.accessToken,
502 };
503 DmAccessCallee dmDstCallee = {
504 .networkId = dstNetworkId,
505 .peerId = "",
506 };
507 HILOGI("dmSrcCaller netWorkId %{public}s, accountId %{public}s, userId %{public}s, pkgName %{public}s; "
508 "dmDstCallee networkId %{public}s.", GetAnonymStr(dmSrcCaller.networkId).c_str(),
509 GetAnonymStr(dmSrcCaller.accountId).c_str(), GetAnonymInt32(dmSrcCaller.userId).c_str(),
510 dmSrcCaller.pkgName.c_str(), GetAnonymStr(dmDstCallee.networkId).c_str());
511
512 #ifdef DMSFWK_SAME_ACCOUNT
513 if (DeviceManager::GetInstance().CheckIsSameAccount(dmSrcCaller, dmDstCallee)) {
514 return true;
515 }
516 HILOGI("check same account by DM fail, will try check access Group by hichain");
517 #endif
518
519 if (DistributedSchedAdapter::GetInstance().CheckAccessToGroup(udid, targetBundleName)) {
520 return true;
521 }
522
523 HILOGI("Check access Group by hichain fail, will try check different account ACL by DM.");
524 if (DeviceManager::GetInstance().CheckAccessControl(dmSrcCaller, dmDstCallee)) {
525 return true;
526 }
527
528 HILOGE("Check different account ACL by DM fail.");
529 return false;
530 }
531
CheckComponentAccessPermission(const AppExecFwk::AbilityInfo & targetAbility,const CallerInfo & callerInfo,const AccountInfo & accountInfo,const AAFwk::Want & want) const532 bool DistributedSchedPermission::CheckComponentAccessPermission(const AppExecFwk::AbilityInfo& targetAbility,
533 const CallerInfo& callerInfo, const AccountInfo& accountInfo, const AAFwk::Want& want) const
534 {
535 // reject directly when in no account networking environment and target ability is not visible,
536 if (!targetAbility.visible) {
537 HILOGE("target ability is not visible, permission denied!");
538 return false;
539 }
540 HILOGD("check component permission success");
541 return true;
542 }
543
CheckMigrateStartCtrlPer(const AppExecFwk::AbilityInfo & targetAbility,const CallerInfo & callerInfo,const AAFwk::Want & want,bool isSameBundle)544 bool DistributedSchedPermission::CheckMigrateStartCtrlPer(const AppExecFwk::AbilityInfo& targetAbility,
545 const CallerInfo& callerInfo, const AAFwk::Want& want, bool isSameBundle)
546 {
547 std::string bundleName = want.GetBundle();
548 if (!CheckBundleContinueConfig(bundleName)) {
549 HILOGI("App does not allow continue in config file, bundle name %{public}s", bundleName.c_str());
550 return false;
551 }
552
553 // check if continuation with same appid
554 HILOGI("Check migration start control permission with same appid enter.");
555 if (!targetAbility.visible &&
556 !CheckDeviceSecurityLevel(callerInfo.sourceDeviceId, want.GetElement().GetDeviceID())) {
557 HILOGE("check device security level failed!");
558 return false;
559 }
560 if (!isSameBundle) {
561 return true;
562 }
563 if (BundleManagerInternal::IsSameAppId(callerInfo.callerAppId, targetAbility.bundleName)) {
564 HILOGD("the appId is the same, check migration start control permission success!");
565 return true;
566 }
567 HILOGE("the appId is different in the migration scenario, permission denied!");
568 return false;
569 }
570
CheckCollaborateStartCtrlPer(const AppExecFwk::AbilityInfo & targetAbility,const CallerInfo & callerInfo,const AAFwk::Want & want) const571 bool DistributedSchedPermission::CheckCollaborateStartCtrlPer(const AppExecFwk::AbilityInfo& targetAbility,
572 const CallerInfo& callerInfo, const AAFwk::Want& want) const
573 {
574 HILOGI("Check collaboration start control permission enter.");
575 // 1. check background permission
576 if (!CheckBackgroundPermission(targetAbility, callerInfo, want, true)) {
577 HILOGE("Check background permission failed!");
578 return false;
579 }
580 // 2. check device security level
581 if (!targetAbility.visible &&
582 !CheckDeviceSecurityLevel(callerInfo.sourceDeviceId, want.GetElement().GetDeviceID())) {
583 HILOGE("check device security level failed!");
584 return false;
585 }
586 // 3. check start or connect ability with same appid
587 if (BundleManagerInternal::IsSameAppId(callerInfo.callerAppId, targetAbility.bundleName)) {
588 HILOGD("the appId is the same, check permission success!");
589 return true;
590 }
591 // 4. check if target ability is not visible and without PERMISSION_START_INVISIBLE_ABILITY
592 if (!CheckTargetAbilityVisible(targetAbility, callerInfo)) {
593 HILOGE("target ability is not visible and has no PERMISSION_START_INVISIBLE_ABILITY, permission denied!");
594 return false;
595 }
596 // 5. check if service of fa mode can associatedWakeUp
597 if (!targetAbility.isStageBasedModel && targetAbility.type == AppExecFwk::AbilityType::SERVICE &&
598 !targetAbility.applicationInfo.associatedWakeUp) {
599 HILOGE("target ability is service ability(FA) and associatedWakeUp is false, permission denied!");
600 return false;
601 }
602 HILOGD("Check collaboration start control permission success");
603 return true;
604 }
605
CheckStartControlPermission(const AppExecFwk::AbilityInfo & targetAbility,const CallerInfo & callerInfo,const AAFwk::Want & want,bool isSameBundle)606 bool DistributedSchedPermission::CheckStartControlPermission(const AppExecFwk::AbilityInfo& targetAbility,
607 const CallerInfo& callerInfo, const AAFwk::Want& want, bool isSameBundle)
608 {
609 HILOGD("Check start control permission enter");
610 return ((want.GetFlags() & AAFwk::Want::FLAG_ABILITY_CONTINUATION) != 0) ?
611 CheckMigrateStartCtrlPer(targetAbility, callerInfo, want, isSameBundle) :
612 CheckCollaborateStartCtrlPer(targetAbility, callerInfo, want);
613 }
614
CheckBackgroundPermission(const AppExecFwk::AbilityInfo & targetAbility,const CallerInfo & callerInfo,const AAFwk::Want & want,bool needCheckApiVersion) const615 bool DistributedSchedPermission::CheckBackgroundPermission(const AppExecFwk::AbilityInfo& targetAbility,
616 const CallerInfo& callerInfo, const AAFwk::Want& want, bool needCheckApiVersion) const
617 {
618 if (callerInfo.extraInfoJson.empty() ||
619 callerInfo.extraInfoJson.find(DMS_VERSION_ID) == callerInfo.extraInfoJson.end()) {
620 HILOGD("the version is low");
621 return true;
622 }
623 AAFwk::Want* remoteWant = const_cast<Want*>(&want);
624 bool isCallerBackGround = remoteWant->GetBoolParam(DMS_IS_CALLER_BACKGROUND, true);
625 remoteWant->RemoveParam(DMS_IS_CALLER_BACKGROUND);
626 if (!isCallerBackGround) {
627 HILOGD("the app is foreground");
628 return true;
629 }
630 int apiVersion = remoteWant->GetIntParam(DMS_API_VERSION, DEFAULT_DMS_API_VERSION);
631 remoteWant->RemoveParam(DMS_API_VERSION);
632 // service in fa mode(API 8) do not need check
633 if (needCheckApiVersion && CheckMinApiVersion(targetAbility, apiVersion)) {
634 HILOGD("the app is service ability of fa mode and is under api 8");
635 return true;
636 }
637 uint32_t dAccessToken = AccessToken::AccessTokenKit::AllocLocalTokenID(callerInfo.sourceDeviceId,
638 callerInfo.accessToken);
639 if (dAccessToken == 0) {
640 HILOGE("dAccessTokenID is invalid!");
641 return false;
642 }
643 // check if background's ability has PERMISSION_START_ABILITIES_FROM_BACKGROUND
644 if (CheckPermission(dAccessToken, PERMISSION_START_ABILITIES_FROM_BACKGROUND) == ERR_OK ||
645 CheckPermission(dAccessToken, PERMISSION_START_ABILIIES_FROM_BACKGROUND) == ERR_OK) {
646 HILOGD("the app has PERMISSION_START_ABILITIES_FROM_BACKGROUND");
647 return true;
648 }
649 HILOGE("CheckBackgroundPermission failed!");
650 return false;
651 }
652
CheckMinApiVersion(const AppExecFwk::AbilityInfo & targetAbility,int32_t apiVersion) const653 bool DistributedSchedPermission::CheckMinApiVersion(const AppExecFwk::AbilityInfo& targetAbility,
654 int32_t apiVersion) const
655 {
656 if (!targetAbility.isStageBasedModel && targetAbility.type == AppExecFwk::AbilityType::SERVICE &&
657 apiVersion <= FA_MODULE_ALLOW_MIN_API_VERSION) {
658 HILOGD("CheckMinApiVersion pass");
659 return true;
660 }
661 return false;
662 }
663
CheckDeviceSecurityLevel(const std::string & srcDeviceId,const std::string & dstDeviceId) const664 bool DistributedSchedPermission::CheckDeviceSecurityLevel(const std::string& srcDeviceId,
665 const std::string& dstDeviceId) const
666 {
667 std::string srcUdid = DnetworkAdapter::GetInstance()->GetUdidByNetworkId(srcDeviceId);
668 if (srcUdid.empty()) {
669 HILOGE("src udid is empty");
670 return false;
671 }
672 std::string dstUdid = DnetworkAdapter::GetInstance()->GetUdidByNetworkId(dstDeviceId);
673 if (dstUdid.empty()) {
674 HILOGE("dst udid is empty");
675 return false;
676 }
677 int32_t srcDeviceSecurityLevel = GetDeviceSecurityLevel(srcUdid);
678 int32_t dstDeviceSecurityLevel = GetDeviceSecurityLevel(dstUdid);
679 if (srcDeviceSecurityLevel == DEFAULT_DEVICE_SECURITY_LEVEL ||
680 srcDeviceSecurityLevel < dstDeviceSecurityLevel) {
681 HILOGE("the device security of source device is lower");
682 return false;
683 }
684 return true;
685 }
686
GetDeviceSecurityLevel(const std::string & udid) const687 int32_t DistributedSchedPermission::GetDeviceSecurityLevel(const std::string& udid) const
688 {
689 DeviceIdentify devIdentify;
690 devIdentify.length = DEVICE_ID_MAX_LEN;
691 int32_t ret = memcpy_s(devIdentify.identity, DEVICE_ID_MAX_LEN, udid.c_str(), udid.length());
692 if (ret != 0) {
693 HILOGE("str copy failed %{public}d", ret);
694 return DEFAULT_DEVICE_SECURITY_LEVEL;
695 }
696 DeviceSecurityInfo *info = nullptr;
697 ret = RequestDeviceSecurityInfo(&devIdentify, nullptr, &info);
698 if (ret != SUCCESS) {
699 HILOGE("request device security info failed %{public}d", ret);
700 FreeDeviceSecurityInfo(info);
701 info = nullptr;
702 return DEFAULT_DEVICE_SECURITY_LEVEL;
703 }
704 int32_t level = 0;
705 ret = GetDeviceSecurityLevelValue(info, &level);
706 HILOGD("get device security level, level is %{public}d", level);
707 FreeDeviceSecurityInfo(info);
708 info = nullptr;
709 if (ret != SUCCESS) {
710 HILOGE("get device security level failed %{public}d", ret);
711 return DEFAULT_DEVICE_SECURITY_LEVEL;
712 }
713 return level;
714 }
715
CheckTargetAbilityVisible(const AppExecFwk::AbilityInfo & targetAbility,const CallerInfo & callerInfo) const716 bool DistributedSchedPermission::CheckTargetAbilityVisible(const AppExecFwk::AbilityInfo& targetAbility,
717 const CallerInfo& callerInfo) const
718 {
719 if (targetAbility.visible) {
720 HILOGD("Target ability is visible.");
721 return true;
722 }
723 uint32_t dAccessToken = AccessToken::AccessTokenKit::AllocLocalTokenID(callerInfo.sourceDeviceId,
724 callerInfo.accessToken);
725 if (dAccessToken == 0) {
726 HILOGE("dAccessTokenID is invalid!");
727 return false;
728 }
729 if (CheckPermissionAll(dAccessToken, PERMISSION_START_INVISIBLE_ABILITY) != ERR_OK) {
730 HILOGE("CheckTargetAbilityVisible failed.");
731 return false;
732 }
733 HILOGD("CheckTargetAbilityVisible passed.");
734 return true;
735 }
736
RemoveRemoteObjectFromWant(std::shared_ptr<AAFwk::Want> want) const737 void DistributedSchedPermission::RemoveRemoteObjectFromWant(std::shared_ptr<AAFwk::Want> want) const
738 {
739 if (want == nullptr) {
740 return;
741 }
742 WantParams wantParams = want->GetParams();
743 std::map<std::string, sptr<IInterface>> params = wantParams.GetParams();
744 for (auto param : params) {
745 sptr<IInterface> object = param.second;
746 IWantParams *wp = IWantParams::Query(object);
747 if (wp == nullptr) {
748 continue;
749 }
750 WantParams value = WantParamWrapper::Unbox(wp);
751 auto type = value.GetParam(TYPE_PROPERTY);
752 AAFwk::IString *typeP = AAFwk::IString::Query(type);
753 if (typeP == nullptr) {
754 continue;
755 }
756 std::string typeValue = AAFwk::String::Unbox(typeP);
757 if (typeValue == REMOTE_OBJECT) {
758 wantParams.Remove(param.first);
759 }
760 }
761 want->SetParams(wantParams);
762 }
763 }
764 }
765