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 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     // check if continuation with same appid
549     HILOGI("Check migration start control permission with same appid enter.");
550     if (!targetAbility.visible &&
551         !CheckDeviceSecurityLevel(callerInfo.sourceDeviceId, want.GetElement().GetDeviceID())) {
552         HILOGE("check device security level failed!");
553         return false;
554         }
555     if (!isSameBundle) {
556         return true;
557     }
558     if (BundleManagerInternal::IsSameAppId(callerInfo.callerAppId, targetAbility.bundleName)) {
559         HILOGD("the appId is the same, check migration start control permission success!");
560         return true;
561     }
562     HILOGE("the appId is different in the migration scenario, permission denied!");
563     return false;
564 }
565 
CheckCollaborateStartCtrlPer(const AppExecFwk::AbilityInfo& targetAbility, const CallerInfo& callerInfo, const AAFwk::Want& want) const566 bool DistributedSchedPermission::CheckCollaborateStartCtrlPer(const AppExecFwk::AbilityInfo& targetAbility,
567     const CallerInfo& callerInfo, const AAFwk::Want& want) const
568 {
569     HILOGI("Check collaboration start control permission enter.");
570     // 1. check background permission
571     if (!CheckBackgroundPermission(targetAbility, callerInfo, want, true)) {
572         HILOGE("Check background permission failed!");
573         return false;
574     }
575     // 2. check device security level
576     if (!targetAbility.visible &&
577         !CheckDeviceSecurityLevel(callerInfo.sourceDeviceId, want.GetElement().GetDeviceID())) {
578         HILOGE("check device security level failed!");
579         return false;
580     }
581     // 3. check start or connect ability with same appid
582     if (BundleManagerInternal::IsSameAppId(callerInfo.callerAppId, targetAbility.bundleName)) {
583         HILOGD("the appId is the same, check permission success!");
584         return true;
585     }
586     // 4. check if target ability is not visible and without PERMISSION_START_INVISIBLE_ABILITY
587     if (!CheckTargetAbilityVisible(targetAbility, callerInfo)) {
588         HILOGE("target ability is not visible and has no PERMISSION_START_INVISIBLE_ABILITY, permission denied!");
589         return false;
590     }
591     // 5. check if service of fa mode can associatedWakeUp
592     if (!targetAbility.isStageBasedModel && targetAbility.type == AppExecFwk::AbilityType::SERVICE &&
593         !targetAbility.applicationInfo.associatedWakeUp) {
594         HILOGE("target ability is service ability(FA) and associatedWakeUp is false, permission denied!");
595         return false;
596     }
597     HILOGD("Check collaboration start control permission success");
598     return true;
599 }
600 
CheckStartControlPermission(const AppExecFwk::AbilityInfo& targetAbility, const CallerInfo& callerInfo, const AAFwk::Want& want, bool isSameBundle)601 bool DistributedSchedPermission::CheckStartControlPermission(const AppExecFwk::AbilityInfo& targetAbility,
602     const CallerInfo& callerInfo, const AAFwk::Want& want, bool isSameBundle)
603 {
604     HILOGD("Check start control permission enter");
605     return ((want.GetFlags() & AAFwk::Want::FLAG_ABILITY_CONTINUATION) != 0) ?
606         CheckMigrateStartCtrlPer(targetAbility, callerInfo, want, isSameBundle) :
607         CheckCollaborateStartCtrlPer(targetAbility, callerInfo, want);
608 }
609 
CheckBackgroundPermission(const AppExecFwk::AbilityInfo& targetAbility, const CallerInfo& callerInfo, const AAFwk::Want& want, bool needCheckApiVersion) const610 bool DistributedSchedPermission::CheckBackgroundPermission(const AppExecFwk::AbilityInfo& targetAbility,
611     const CallerInfo& callerInfo, const AAFwk::Want& want, bool needCheckApiVersion) const
612 {
613     if (callerInfo.extraInfoJson.empty() ||
614         callerInfo.extraInfoJson.find(DMS_VERSION_ID) == callerInfo.extraInfoJson.end()) {
615         HILOGD("the version is low");
616         return true;
617     }
618     AAFwk::Want* remoteWant = const_cast<Want*>(&want);
619     bool isCallerBackGround = remoteWant->GetBoolParam(DMS_IS_CALLER_BACKGROUND, true);
620     remoteWant->RemoveParam(DMS_IS_CALLER_BACKGROUND);
621     if (!isCallerBackGround) {
622         HILOGD("the app is foreground");
623         return true;
624     }
625     int apiVersion = remoteWant->GetIntParam(DMS_API_VERSION, DEFAULT_DMS_API_VERSION);
626     remoteWant->RemoveParam(DMS_API_VERSION);
627     // service in fa mode(API 8) do not need check
628     if (needCheckApiVersion && CheckMinApiVersion(targetAbility, apiVersion)) {
629         HILOGD("the app is service ability of fa mode and is under api 8");
630         return true;
631     }
632     uint32_t dAccessToken = AccessToken::AccessTokenKit::AllocLocalTokenID(callerInfo.sourceDeviceId,
633         callerInfo.accessToken);
634     if (dAccessToken == 0) {
635         HILOGE("dAccessTokenID is invalid!");
636         return false;
637     }
638     // check if background's ability has PERMISSION_START_ABILITIES_FROM_BACKGROUND
639     if (CheckPermission(dAccessToken, PERMISSION_START_ABILITIES_FROM_BACKGROUND) == ERR_OK ||
640         CheckPermission(dAccessToken, PERMISSION_START_ABILIIES_FROM_BACKGROUND) == ERR_OK) {
641         HILOGD("the app has PERMISSION_START_ABILITIES_FROM_BACKGROUND");
642         return true;
643     }
644     HILOGE("CheckBackgroundPermission failed!");
645     return false;
646 }
647 
CheckMinApiVersion(const AppExecFwk::AbilityInfo& targetAbility, int32_t apiVersion) const648 bool DistributedSchedPermission::CheckMinApiVersion(const AppExecFwk::AbilityInfo& targetAbility,
649     int32_t apiVersion) const
650 {
651     if (!targetAbility.isStageBasedModel && targetAbility.type == AppExecFwk::AbilityType::SERVICE &&
652         apiVersion <= FA_MODULE_ALLOW_MIN_API_VERSION) {
653         HILOGD("CheckMinApiVersion pass");
654         return true;
655     }
656     return false;
657 }
658 
CheckDeviceSecurityLevel(const std::string& srcDeviceId, const std::string& dstDeviceId) const659 bool DistributedSchedPermission::CheckDeviceSecurityLevel(const std::string& srcDeviceId,
660     const std::string& dstDeviceId) const
661 {
662     std::string srcUdid = DnetworkAdapter::GetInstance()->GetUdidByNetworkId(srcDeviceId);
663     if (srcUdid.empty()) {
664         HILOGE("src udid is empty");
665         return false;
666     }
667     std::string dstUdid = DnetworkAdapter::GetInstance()->GetUdidByNetworkId(dstDeviceId);
668     if (dstUdid.empty()) {
669         HILOGE("dst udid is empty");
670         return false;
671     }
672     int32_t srcDeviceSecurityLevel = GetDeviceSecurityLevel(srcUdid);
673     int32_t dstDeviceSecurityLevel = GetDeviceSecurityLevel(dstUdid);
674     if (srcDeviceSecurityLevel == DEFAULT_DEVICE_SECURITY_LEVEL ||
675         srcDeviceSecurityLevel < dstDeviceSecurityLevel) {
676         HILOGE("the device security of source device is lower");
677         return false;
678     }
679     return true;
680 }
681 
GetDeviceSecurityLevel(const std::string& udid) const682 int32_t DistributedSchedPermission::GetDeviceSecurityLevel(const std::string& udid) const
683 {
684     DeviceIdentify devIdentify;
685     devIdentify.length = DEVICE_ID_MAX_LEN;
686     int32_t ret = memcpy_s(devIdentify.identity, DEVICE_ID_MAX_LEN, udid.c_str(), udid.length());
687     if (ret != 0) {
688         HILOGE("str copy failed %{public}d", ret);
689         return DEFAULT_DEVICE_SECURITY_LEVEL;
690     }
691     DeviceSecurityInfo *info = nullptr;
692     ret = RequestDeviceSecurityInfo(&devIdentify, nullptr, &info);
693     if (ret != SUCCESS) {
694         HILOGE("request device security info failed %{public}d", ret);
695         FreeDeviceSecurityInfo(info);
696         info = nullptr;
697         return DEFAULT_DEVICE_SECURITY_LEVEL;
698     }
699     int32_t level = 0;
700     ret = GetDeviceSecurityLevelValue(info, &level);
701     HILOGD("get device security level, level is %{public}d", level);
702     FreeDeviceSecurityInfo(info);
703     info = nullptr;
704     if (ret != SUCCESS) {
705         HILOGE("get device security level failed %{public}d", ret);
706         return DEFAULT_DEVICE_SECURITY_LEVEL;
707     }
708     return level;
709 }
710 
CheckTargetAbilityVisible(const AppExecFwk::AbilityInfo& targetAbility, const CallerInfo& callerInfo) const711 bool DistributedSchedPermission::CheckTargetAbilityVisible(const AppExecFwk::AbilityInfo& targetAbility,
712     const CallerInfo& callerInfo) const
713 {
714     if (targetAbility.visible) {
715         HILOGD("Target ability is visible.");
716         return true;
717     }
718     uint32_t dAccessToken = AccessToken::AccessTokenKit::AllocLocalTokenID(callerInfo.sourceDeviceId,
719         callerInfo.accessToken);
720     if (dAccessToken == 0) {
721         HILOGE("dAccessTokenID is invalid!");
722         return false;
723     }
724     if (CheckPermissionAll(dAccessToken, PERMISSION_START_INVISIBLE_ABILITY) != ERR_OK) {
725         HILOGE("CheckTargetAbilityVisible failed.");
726         return false;
727     }
728     HILOGD("CheckTargetAbilityVisible passed.");
729     return true;
730 }
731 
RemoveRemoteObjectFromWant(std::shared_ptr<AAFwk::Want> want) const732 void DistributedSchedPermission::RemoveRemoteObjectFromWant(std::shared_ptr<AAFwk::Want> want) const
733 {
734     if (want == nullptr) {
735         return;
736     }
737     WantParams wantParams = want->GetParams();
738     std::map<std::string, sptr<IInterface>> params = wantParams.GetParams();
739     for (auto param : params) {
740         sptr<IInterface> object = param.second;
741         IWantParams *wp = IWantParams::Query(object);
742         if (wp == nullptr) {
743             continue;
744         }
745         WantParams value = WantParamWrapper::Unbox(wp);
746         auto type = value.GetParam(TYPE_PROPERTY);
747         AAFwk::IString *typeP = AAFwk::IString::Query(type);
748         if (typeP == nullptr) {
749             continue;
750         }
751         std::string typeValue = AAFwk::String::Unbox(typeP);
752         if (typeValue == REMOTE_OBJECT) {
753             wantParams.Remove(param.first);
754         }
755     }
756     want->SetParams(wantParams);
757 }
758 }
759 }
760