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