• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2023 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 "adapter/dnetwork_adapter.h"
20 #include "bundle/bundle_manager_internal.h"
21 #include "caller_info.h"
22 #include "datetime_ex.h"
23 #include "device_auth_defines.h"
24 #include "device_security_defines.h"
25 #include "device_security_info.h"
26 #include "distributed_sched_adapter.h"
27 #include "dtbschedmgr_log.h"
28 #include "ipc_skeleton.h"
29 #include "json_util.h"
30 #include "os_account_manager.h"
31 
32 namespace OHOS {
33 namespace DistributedSchedule {
34 using namespace OHOS::Security;
35 using namespace AAFwk;
36 namespace {
37 const std::string FOUNDATION_PROCESS_NAME = "foundation";
38 const std::string DMS_API_VERSION = "dmsApiVersion";
39 const std::string DMS_IS_CALLER_BACKGROUND = "dmsIsCallerBackGround";
40 const std::string DMS_MISSION_ID = "dmsMissionId";
41 const std::string DMS_VERSION_ID = "dmsVersion";
42 const std::string PARAMS_URI = "ability.verify.uri";
43 const std::string PARAMS_STREAM = "ability.params.stream";
44 const std::string PERMISSION_START_ABILIIES_FROM_BACKGROUND = "ohos.permission.START_ABILIIES_FROM_BACKGROUND";
45 const std::string PERMISSION_START_ABILITIES_FROM_BACKGROUND = "ohos.permission.START_ABILITIES_FROM_BACKGROUND";
46 const std::string PERMISSION_START_INVISIBLE_ABILITY = "ohos.permission.START_INVISIBLE_ABILITY";
47 const std::string DISTRIBUTED_FILES_PATH = "/data/storage/el2/distributedfiles/";
48 const std::string BUNDLE_NAME_SCENEBOARD = "com.ohos.sceneboard";
49 constexpr int32_t DEFAULT_DMS_API_VERSION = 9;
50 const int DEFAULT_DMS_MISSION_ID = -1;
51 const int FA_MODULE_ALLOW_MIN_API_VERSION = 8;
52 const int DEFAULT_DEVICE_SECURITY_LEVEL = -1;
53 }
54 IMPLEMENT_SINGLE_INSTANCE(DistributedSchedPermission);
from_json(const nlohmann::json & jsonObject,GroupInfo & groupInfo)55 void from_json(const nlohmann::json& jsonObject, GroupInfo& groupInfo)
56 {
57     const auto &jsonObjectEnd = jsonObject.end();
58     int32_t parseResult = ERR_OK;
59     GetValueIfFindKey<std::string>(jsonObject,
60         jsonObjectEnd,
61         FIELD_GROUP_NAME,
62         groupInfo.groupName,
63         JsonType::STRING,
64         false,
65         parseResult,
66         ArrayType::NOT_ARRAY);
67     GetValueIfFindKey<std::string>(jsonObject,
68         jsonObjectEnd,
69         FIELD_GROUP_ID,
70         groupInfo.groupId,
71         JsonType::STRING,
72         false,
73         parseResult,
74         ArrayType::NOT_ARRAY);
75     GetValueIfFindKey<std::string>(jsonObject,
76         jsonObjectEnd,
77         FIELD_GROUP_OWNER,
78         groupInfo.groupOwner,
79         JsonType::STRING,
80         false,
81         parseResult,
82         ArrayType::NOT_ARRAY);
83     GetValueIfFindKey<int32_t>(jsonObject,
84         jsonObjectEnd,
85         FIELD_GROUP_TYPE,
86         groupInfo.groupType,
87         JsonType::NUMBER,
88         false,
89         parseResult,
90         ArrayType::NOT_ARRAY);
91     GetValueIfFindKey<int32_t>(jsonObject,
92         jsonObjectEnd,
93         FIELD_GROUP_VISIBILITY,
94         groupInfo.groupVisibility,
95         JsonType::NUMBER,
96         false,
97         parseResult,
98         ArrayType::NOT_ARRAY);
99 }
100 
CheckSendResultPermission(const AAFwk::Want & want,const CallerInfo & callerInfo,const AccountInfo & accountInfo,AppExecFwk::AbilityInfo & targetAbility)101 int32_t DistributedSchedPermission::CheckSendResultPermission(const AAFwk::Want& want, const CallerInfo& callerInfo,
102     const AccountInfo& accountInfo, AppExecFwk::AbilityInfo& targetAbility)
103 {
104     // 1.check account access permission in no account networking environment.
105     if (!CheckAccountAccessPermission(callerInfo, accountInfo, targetAbility.bundleName)) {
106         HILOGE("CheckAccountAccessPermission denied or failed!");
107         return DMS_ACCOUNT_ACCESS_PERMISSION_DENIED;
108     }
109     // 2.check component access permission, when the ability is not visible.
110     if (!CheckComponentAccessPermission(targetAbility, callerInfo, accountInfo, want)) {
111         HILOGE("CheckComponentAccessPermission denied or failed! the callee component do not have permission");
112         return DMS_COMPONENT_ACCESS_PERMISSION_DENIED;
113     }
114     HILOGI("CheckSendResultPermission success!!");
115     return ERR_OK;
116 }
117 
CheckStartPermission(const AAFwk::Want & want,const CallerInfo & callerInfo,const AccountInfo & accountInfo,AppExecFwk::AbilityInfo & targetAbility)118 int32_t DistributedSchedPermission::CheckStartPermission(const AAFwk::Want& want, const CallerInfo& callerInfo,
119     const AccountInfo& accountInfo, AppExecFwk::AbilityInfo& targetAbility)
120 {
121     // 1.check account access permission in no account networking environment.
122     if (!CheckAccountAccessPermission(callerInfo, accountInfo, targetAbility.bundleName)) {
123         HILOGE("CheckAccountAccessPermission denied or failed!");
124         return DMS_ACCOUNT_ACCESS_PERMISSION_DENIED;
125     }
126     // 2.check start control permissions.
127     if (!CheckStartControlPermission(targetAbility, callerInfo, want)) {
128         HILOGE("CheckStartControlPermission denied or failed! the callee component do not have permission");
129         return DMS_START_CONTROL_PERMISSION_DENIED;
130     }
131     HILOGI("CheckDistributedPermission success!!");
132     return ERR_OK;
133 }
134 
GetAccountInfo(const std::string & remoteNetworkId,const CallerInfo & callerInfo,AccountInfo & accountInfo)135 int32_t DistributedSchedPermission::GetAccountInfo(const std::string& remoteNetworkId,
136     const CallerInfo& callerInfo, AccountInfo& accountInfo)
137 {
138     if (remoteNetworkId.empty()) {
139         HILOGE("remoteNetworkId is empty");
140         return ERR_NULL_OBJECT;
141     }
142     std::string udid = DnetworkAdapter::GetInstance()->GetUdidByNetworkId(remoteNetworkId);
143     if (udid.empty()) {
144         HILOGE("udid is empty");
145         return ERR_NULL_OBJECT;
146     }
147     if (!GetRelatedGroups(udid, callerInfo.bundleNames, accountInfo)) {
148         HILOGE("GetRelatedGroups failed");
149         return INVALID_PARAMETERS_ERR;
150     }
151     return ERR_OK;
152 }
153 
GetRelatedGroups(const std::string & udid,const std::vector<std::string> & bundleNames,AccountInfo & accountInfo)154 bool DistributedSchedPermission::GetRelatedGroups(const std::string& udid,
155     const std::vector<std::string>& bundleNames, AccountInfo& accountInfo)
156 {
157     for (const auto& bundleName : bundleNames) {
158         std::string returnGroups;
159         if (!DistributedSchedAdapter::GetInstance().GetRelatedGroups(udid, bundleName, returnGroups)) {
160             continue;
161         }
162         std::vector<GroupInfo> groupInfos;
163         if (!ParseGroupInfos(returnGroups, groupInfos)) {
164             continue;
165         }
166         for (const auto& groupInfo : groupInfos) {
167             // check group type is whether (same count or point to point) or not
168             if (groupInfo.groupType != GroupType::IDENTICAL_ACCOUNT_GROUP
169                 && groupInfo.groupType != GroupType::PEER_TO_PEER_GROUP) {
170                 continue;
171             }
172             accountInfo.groupIdList.push_back(groupInfo.groupId);
173             if (groupInfo.groupType == GroupType::IDENTICAL_ACCOUNT_GROUP
174                 && accountInfo.accountType != IDistributedSched::SAME_ACCOUNT_TYPE) {
175                 accountInfo.accountType = IDistributedSched::SAME_ACCOUNT_TYPE;
176             }
177         }
178     }
179     if (accountInfo.groupIdList.empty()) {
180         HILOGE("groupIdList is empty");
181         return false;
182     }
183     return true;
184 }
185 
ParseGroupInfos(const std::string & returnGroupStr,std::vector<GroupInfo> & groupInfos)186 bool DistributedSchedPermission::ParseGroupInfos(const std::string& returnGroupStr, std::vector<GroupInfo>& groupInfos)
187 {
188     nlohmann::json groupInfoJson = nlohmann::json::parse(returnGroupStr, nullptr, false);
189     if (groupInfoJson.is_discarded()) {
190         HILOGE("returnGroupStr parse failed");
191         return false;
192     }
193     HILOGD("groupInfoJson:%{public}s", groupInfoJson.dump().c_str());
194     groupInfos = groupInfoJson.get<std::vector<GroupInfo>>();
195     if (groupInfos.empty()) {
196         HILOGE("groupInfos is empty");
197         return false;
198     }
199     return true;
200 }
201 
GetTargetAbility(const AAFwk::Want & want,AppExecFwk::AbilityInfo & targetAbility,bool needQueryExtension) const202 bool DistributedSchedPermission::GetTargetAbility(const AAFwk::Want& want,
203     AppExecFwk::AbilityInfo& targetAbility, bool needQueryExtension) const
204 {
205     if (BundleManagerInternal::QueryAbilityInfo(want, targetAbility)) {
206         if (want.GetIntParam(DMS_MISSION_ID, DEFAULT_DMS_MISSION_ID) != DEFAULT_DMS_MISSION_ID &&
207             (targetAbility.type == AppExecFwk::AbilityType::SERVICE ||
208             targetAbility.type == AppExecFwk::AbilityType::EXTENSION)) {
209             HILOGE("StartAbilityForResult can not start service and extension ability");
210             return false;
211         }
212         return true;
213     }
214     if (needQueryExtension) {
215         HILOGI("QueryAbilityInfo failed, try to QueryExtensionAbilityInfo");
216         // try to find extension
217         AppExecFwk::ExtensionAbilityInfo extensionAbility;
218         if (BundleManagerInternal::QueryExtensionAbilityInfo(want, extensionAbility)) {
219             // extensionAbilityInfo translates to abilityInfo
220             BundleManagerInternal::InitAbilityInfoFromExtension(extensionAbility, targetAbility);
221             return true;
222         }
223     }
224     HILOGE("QueryAbilityInfo failed, want bundle name=%{public}s, ability name=%{public}s.",
225         want.GetElement().GetBundleName().c_str(), want.GetElement().GetAbilityName().c_str());
226     return false;
227 }
228 
CheckGetCallerPermission(const AAFwk::Want & want,const CallerInfo & callerInfo,const AccountInfo & accountInfo,AppExecFwk::AbilityInfo & targetAbility)229 int32_t DistributedSchedPermission::CheckGetCallerPermission(const AAFwk::Want& want, const CallerInfo& callerInfo,
230     const AccountInfo& accountInfo, AppExecFwk::AbilityInfo& targetAbility)
231 {
232     // 1.check account access permission in no account networking environment.
233     if (!CheckAccountAccessPermission(callerInfo, accountInfo, targetAbility.bundleName)) {
234         HILOGE("CheckAccountAccessPermission denied or failed!");
235         return DMS_ACCOUNT_ACCESS_PERMISSION_DENIED;
236     }
237     // 2. check call with same appid
238     if (!BundleManagerInternal::IsSameAppId(callerInfo.callerAppId, targetAbility.bundleName)) {
239         HILOGE("the appId is different, check permission denied!");
240         return CALL_PERMISSION_DENIED;
241     }
242     // 3. check background permission
243     if (!CheckBackgroundPermission(targetAbility, callerInfo, want, false)) {
244         HILOGE("Check background permission failed!");
245         return DMS_BACKGROUND_PERMISSION_DENIED;
246     }
247     // 4. check device security level
248     if (!targetAbility.visible &&
249         !CheckDeviceSecurityLevel(callerInfo.sourceDeviceId, want.GetElement().GetDeviceID())) {
250         HILOGE("check device security level failed!");
251         return CALL_PERMISSION_DENIED;
252     }
253     HILOGI("CheckGetCallerPermission success!!");
254     return ERR_OK;
255 }
256 
IsFoundationCall() const257 bool DistributedSchedPermission::IsFoundationCall() const
258 {
259     uint32_t accessToken = IPCSkeleton::GetCallingTokenID();
260     AccessToken::NativeTokenInfo nativeTokenInfo;
261     int32_t result = AccessToken::AccessTokenKit::GetNativeTokenInfo(accessToken, nativeTokenInfo);
262     if (result == ERR_OK && nativeTokenInfo.processName == FOUNDATION_PROCESS_NAME) {
263         return true;
264     }
265     HILOGE("not foundation called, processName:%{private}s", nativeTokenInfo.processName.c_str());
266     return false;
267 }
268 
IsSceneBoardCall() const269 bool DistributedSchedPermission::IsSceneBoardCall() const
270 {
271     int32_t activeAccountId = 0;
272 #ifdef OS_ACCOUNT_PART
273     std::vector<int32_t> ids;
274     int32_t errCode = AccountSA::OsAccountManager::QueryActiveOsAccountIds(ids);
275     if (errCode != ERR_OK || ids.empty()) {
276         HILOGE("QueryActiveOsAccountIds failed.");
277         return false;
278     }
279     activeAccountId = ids[0];
280 #endif
281     AppExecFwk::ApplicationInfo appInfo;
282     if (BundleManagerInternal::GetApplicationInfoFromBms(BUNDLE_NAME_SCENEBOARD,
283         AppExecFwk::BundleFlag::GET_BUNDLE_DEFAULT, activeAccountId, appInfo) != ERR_OK) {
284         HILOGE("get applicationInfo failed.");
285         return false;
286     }
287     auto accessTokenId = IPCSkeleton::GetCallingTokenID();
288     if (accessTokenId != appInfo.accessTokenId) {
289         HILOGE("not sceneBoard called.");
290         return false;
291     }
292     return true;
293 }
294 
CheckPermission(uint32_t accessToken,const std::string & permissionName) const295 int32_t DistributedSchedPermission::CheckPermission(uint32_t accessToken, const std::string& permissionName) const
296 {
297     HILOGI("CheckPermission called.");
298     if (VerifyPermission(accessToken, permissionName)) {
299         return ERR_OK;
300     }
301     return DMS_PERMISSION_DENIED;
302 }
303 
CheckPermissionAll(uint32_t accessToken,const std::string & permissionName) const304 int32_t DistributedSchedPermission::CheckPermissionAll(uint32_t accessToken, const std::string& permissionName) const
305 {
306     HILOGI("CheckPermissionAll called.");
307     if (VerifyPermission(accessToken, permissionName)) {
308         return ERR_OK;
309     }
310     return DMS_PERMISSION_DENIED;
311 }
312 
MarkUriPermission(OHOS::AAFwk::Want & want,uint32_t accessToken)313 void DistributedSchedPermission::MarkUriPermission(OHOS::AAFwk::Want& want, uint32_t accessToken)
314 {
315     if ((want.GetFlags() & (Want::FLAG_AUTH_READ_URI_PERMISSION | Want::FLAG_AUTH_WRITE_URI_PERMISSION)) == 0) {
316         return;
317     }
318     auto bms = BundleManagerInternal::GetBundleManager();
319     if (bms == nullptr) {
320         HILOGW("Failed to get bms.");
321         return;
322     }
323     std::vector<std::string> uriVec = want.GetStringArrayParam(PARAMS_STREAM);
324     std::string uriStr = want.GetUri().ToString();
325     uriVec.emplace_back(uriStr);
326     std::vector<std::string> uriVecPermission;
327     HILOGI("GrantUriPermission uriVec size: %{public}zu", uriVec.size());
328     for (std::string str : uriVec) {
329         Uri uri(str);
330         if (!IsDistributedFile(uri.GetPath())) {
331             continue;
332         }
333         std::string authority = uri.GetAuthority();
334         HILOGI("uri authority is %{public}s.", authority.c_str());
335         AppExecFwk::BundleInfo bundleInfo;
336         int32_t activeAccountId = 0;
337 #ifdef OS_ACCOUNT_PART
338         std::vector<int32_t> ids;
339         int32_t errCode = AccountSA::OsAccountManager::QueryActiveOsAccountIds(ids);
340         if (errCode != ERR_OK || ids.empty()) {
341             return;
342         }
343         activeAccountId = ids[0];
344 #endif
345         if (!bms->GetBundleInfo(authority,
346             AppExecFwk::BundleFlag::GET_BUNDLE_WITH_EXTENSION_INFO, bundleInfo, activeAccountId)) {
347             HILOGW("To fail to get bundle info according to uri.");
348             continue;
349         }
350         if (bundleInfo.applicationInfo.accessTokenId == accessToken) {
351             HILOGI("uri token is true.");
352             uriVecPermission.emplace_back(str);
353         }
354     }
355     want.SetParam(PARAMS_URI, uriVecPermission);
356 }
357 
IsDistributedFile(const std::string & path) const358 bool DistributedSchedPermission::IsDistributedFile(const std::string& path) const
359 {
360     if (path.compare(0, DISTRIBUTED_FILES_PATH.size(), DISTRIBUTED_FILES_PATH) == 0) {
361         return true;
362     }
363     HILOGE("uri path is false.");
364     return false;
365 }
366 
VerifyPermission(uint32_t accessToken,const std::string & permissionName) const367 bool DistributedSchedPermission::VerifyPermission(uint32_t accessToken, const std::string& permissionName) const
368 {
369     int32_t result = AccessToken::AccessTokenKit::VerifyAccessToken(accessToken, permissionName);
370     if (result == AccessToken::PermissionState::PERMISSION_DENIED) {
371         HILOGE("permission denied, permissionName:%{public}s", permissionName.c_str());
372         return false;
373     }
374     HILOGD("permission matched.");
375     return true;
376 }
377 
CheckAccountAccessPermission(const CallerInfo & callerInfo,const AccountInfo & accountInfo,const std::string & targetBundleName)378 bool DistributedSchedPermission::CheckAccountAccessPermission(const CallerInfo& callerInfo,
379     const AccountInfo& accountInfo, const std::string& targetBundleName)
380 {
381     if (accountInfo.accountType == IDistributedSched::SAME_ACCOUNT_TYPE) {
382         HILOGD("no need to check");
383         return true;
384     }
385     if (targetBundleName.empty() || accountInfo.groupIdList.empty()) {
386         HILOGE("targetBundleName or groupIdList is empty");
387         return false;
388     }
389 
390     for (const auto& groupId : accountInfo.groupIdList) {
391         HILOGD("groupId:%{public}s targetBundleName:%{public}s", groupId.c_str(), targetBundleName.c_str());
392         if (DistributedSchedAdapter::GetInstance().CheckAccessToGroup(groupId, targetBundleName)) {
393             return true;
394         }
395     }
396     HILOGE("check account permission failed");
397     return false;
398 }
399 
CheckComponentAccessPermission(const AppExecFwk::AbilityInfo & targetAbility,const CallerInfo & callerInfo,const AccountInfo & accountInfo,const AAFwk::Want & want) const400 bool DistributedSchedPermission::CheckComponentAccessPermission(const AppExecFwk::AbilityInfo& targetAbility,
401     const CallerInfo& callerInfo, const AccountInfo& accountInfo, const AAFwk::Want& want) const
402 {
403     // reject directly when in no account networking environment and target ability is not visible,
404     if (!targetAbility.visible) {
405         HILOGE("target ability is not visible, permission denied!");
406         return false;
407     }
408     HILOGD("check component permission success");
409     return true;
410 }
411 
CheckStartControlPermission(const AppExecFwk::AbilityInfo & targetAbility,const CallerInfo & callerInfo,const AAFwk::Want & want) const412 bool DistributedSchedPermission::CheckStartControlPermission(const AppExecFwk::AbilityInfo& targetAbility,
413     const CallerInfo& callerInfo, const AAFwk::Want& want) const
414 {
415     // 1. check if continuation with same appid
416     if ((want.GetFlags() & AAFwk::Want::FLAG_ABILITY_CONTINUATION) != 0) {
417         if (!targetAbility.visible &&
418             !CheckDeviceSecurityLevel(callerInfo.sourceDeviceId, want.GetElement().GetDeviceID())) {
419             HILOGE("check device security level failed!");
420             return false;
421         }
422         if (BundleManagerInternal::IsSameAppId(callerInfo.callerAppId, targetAbility.bundleName)) {
423             HILOGD("the appId is the same, check permission success!");
424             return true;
425         }
426         HILOGE("the appId is different in the migration scenario, permission denied!");
427         return false;
428     }
429     // 2. check background permission
430     if (!CheckBackgroundPermission(targetAbility, callerInfo, want, true)) {
431         HILOGE("Check background permission failed!");
432         return false;
433     }
434     // 3. check device security level
435     if (!targetAbility.visible &&
436         !CheckDeviceSecurityLevel(callerInfo.sourceDeviceId, want.GetElement().GetDeviceID())) {
437         HILOGE("check device security level failed!");
438         return false;
439     }
440     // 4. check start or connect ability with same appid
441     if (BundleManagerInternal::IsSameAppId(callerInfo.callerAppId, targetAbility.bundleName)) {
442         HILOGD("the appId is the same, check permission success!");
443         return true;
444     }
445     // 5. check if target ability is not visible and without PERMISSION_START_INVISIBLE_ABILITY
446     if (!CheckTargetAbilityVisible(targetAbility, callerInfo)) {
447         HILOGE("target ability is not visible and has no PERMISSION_START_INVISIBLE_ABILITY, permission denied!");
448         return false;
449     }
450     // 6. check if service of fa mode can associatedWakeUp
451     if (!targetAbility.isStageBasedModel && targetAbility.type == AppExecFwk::AbilityType::SERVICE &&
452         !targetAbility.applicationInfo.associatedWakeUp) {
453         HILOGE("target ability is service ability(FA) and associatedWakeUp is false, permission denied!");
454         return false;
455     }
456     HILOGD("CheckStartControlPermission success");
457     return true;
458 }
459 
CheckBackgroundPermission(const AppExecFwk::AbilityInfo & targetAbility,const CallerInfo & callerInfo,const AAFwk::Want & want,bool needCheckApiVersion) const460 bool DistributedSchedPermission::CheckBackgroundPermission(const AppExecFwk::AbilityInfo& targetAbility,
461     const CallerInfo& callerInfo, const AAFwk::Want& want, bool needCheckApiVersion) const
462 {
463     if (callerInfo.extraInfoJson.empty() ||
464         callerInfo.extraInfoJson.find(DMS_VERSION_ID) == callerInfo.extraInfoJson.end()) {
465         HILOGD("the version is low");
466         return true;
467     }
468     AAFwk::Want* remoteWant = const_cast<Want*>(&want);
469     bool isCallerBackGround = remoteWant->GetBoolParam(DMS_IS_CALLER_BACKGROUND, true);
470     remoteWant->RemoveParam(DMS_IS_CALLER_BACKGROUND);
471     if (!isCallerBackGround) {
472         HILOGD("the app is foreground");
473         return true;
474     }
475     int apiVersion = remoteWant->GetIntParam(DMS_API_VERSION, DEFAULT_DMS_API_VERSION);
476     remoteWant->RemoveParam(DMS_API_VERSION);
477     // service in fa mode(API 8) do not need check
478     if (needCheckApiVersion && CheckMinApiVersion(targetAbility, apiVersion)) {
479         HILOGD("the app is service ability of fa mode and is under api 8");
480         return true;
481     }
482     uint32_t dAccessToken = AccessToken::AccessTokenKit::AllocLocalTokenID(callerInfo.sourceDeviceId,
483         callerInfo.accessToken);
484     if (dAccessToken == 0) {
485         HILOGE("dAccessTokenID is invalid!");
486         return false;
487     }
488     // check if background's ability has PERMISSION_START_ABILITIES_FROM_BACKGROUND
489     if (CheckPermission(dAccessToken, PERMISSION_START_ABILITIES_FROM_BACKGROUND) == ERR_OK ||
490         CheckPermission(dAccessToken, PERMISSION_START_ABILIIES_FROM_BACKGROUND) == ERR_OK) {
491         HILOGD("the app has PERMISSION_START_ABILITIES_FROM_BACKGROUND");
492         return true;
493     }
494     HILOGE("CheckBackgroundPermission failed!");
495     return false;
496 }
497 
CheckMinApiVersion(const AppExecFwk::AbilityInfo & targetAbility,int32_t apiVersion) const498 bool DistributedSchedPermission::CheckMinApiVersion(const AppExecFwk::AbilityInfo& targetAbility,
499     int32_t apiVersion) const
500 {
501     if (!targetAbility.isStageBasedModel && targetAbility.type == AppExecFwk::AbilityType::SERVICE &&
502         apiVersion <= FA_MODULE_ALLOW_MIN_API_VERSION) {
503         HILOGD("CheckMinApiVersion pass");
504         return true;
505     }
506     return false;
507 }
508 
CheckDeviceSecurityLevel(const std::string & srcDeviceId,const std::string & dstDeviceId) const509 bool DistributedSchedPermission::CheckDeviceSecurityLevel(const std::string& srcDeviceId,
510     const std::string& dstDeviceId) const
511 {
512     std::string srcUdid = DnetworkAdapter::GetInstance()->GetUdidByNetworkId(srcDeviceId);
513     if (srcUdid.empty()) {
514         HILOGE("src udid is empty");
515         return false;
516     }
517     std::string dstUdid = DnetworkAdapter::GetInstance()->GetUdidByNetworkId(dstDeviceId);
518     if (dstUdid.empty()) {
519         HILOGE("dst udid is empty");
520         return false;
521     }
522     int32_t srcDeviceSecurityLevel = GetDeviceSecurityLevel(srcUdid);
523     int32_t dstDeviceSecurityLevel = GetDeviceSecurityLevel(dstUdid);
524     if (srcDeviceSecurityLevel == DEFAULT_DEVICE_SECURITY_LEVEL ||
525         srcDeviceSecurityLevel < dstDeviceSecurityLevel) {
526         HILOGE("the device security of source device is lower");
527         return false;
528     }
529     return true;
530 }
531 
GetDeviceSecurityLevel(const std::string & udid) const532 int32_t DistributedSchedPermission::GetDeviceSecurityLevel(const std::string& udid) const
533 {
534     DeviceIdentify devIdentify;
535     devIdentify.length = DEVICE_ID_MAX_LEN;
536     int32_t ret = memcpy_s(devIdentify.identity, DEVICE_ID_MAX_LEN, udid.c_str(), DEVICE_ID_MAX_LEN);
537     if (ret != 0) {
538         HILOGE("str copy failed %{public}d", ret);
539         return DEFAULT_DEVICE_SECURITY_LEVEL;
540     }
541     DeviceSecurityInfo *info = nullptr;
542     ret = RequestDeviceSecurityInfo(&devIdentify, nullptr, &info);
543     if (ret != SUCCESS) {
544         HILOGE("request device security info failed %{public}d", ret);
545         FreeDeviceSecurityInfo(info);
546         info = nullptr;
547         return DEFAULT_DEVICE_SECURITY_LEVEL;
548     }
549     int32_t level = 0;
550     ret = GetDeviceSecurityLevelValue(info, &level);
551     HILOGD("get device security level, level is %{public}d", level);
552     FreeDeviceSecurityInfo(info);
553     info = nullptr;
554     if (ret != SUCCESS) {
555         HILOGE("get device security level failed %{public}d", ret);
556         return DEFAULT_DEVICE_SECURITY_LEVEL;
557     }
558     return level;
559 }
560 
CheckTargetAbilityVisible(const AppExecFwk::AbilityInfo & targetAbility,const CallerInfo & callerInfo) const561 bool DistributedSchedPermission::CheckTargetAbilityVisible(const AppExecFwk::AbilityInfo& targetAbility,
562     const CallerInfo& callerInfo) const
563 {
564     if (targetAbility.visible) {
565         HILOGD("Target ability is visible.");
566         return true;
567     }
568     uint32_t dAccessToken = AccessToken::AccessTokenKit::AllocLocalTokenID(callerInfo.sourceDeviceId,
569         callerInfo.accessToken);
570     if (dAccessToken == 0) {
571         HILOGE("dAccessTokenID is invalid!");
572         return false;
573     }
574     if (CheckPermissionAll(dAccessToken, PERMISSION_START_INVISIBLE_ABILITY) != ERR_OK) {
575         HILOGE("CheckTargetAbilityVisible failed.");
576         return false;
577     }
578     HILOGD("CheckTargetAbilityVisible passed.");
579     return true;
580 }
581 }
582 }