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