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 }