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