1 /*
2 * Copyright (c) 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 "interceptor/ability_jump_interceptor.h"
17
18 #include "ability_util.h"
19 #include "accesstoken_kit.h"
20 #include "hitrace_meter.h"
21 #include "permission_constants.h"
22 #include "start_ability_utils.h"
23 #include "system_dialog_scheduler.h"
24
25 namespace OHOS {
26 namespace AAFwk {
27 namespace {
28 constexpr const char* JUMP_DIALOG_CALLER_BUNDLE_NAME = "interceptor_callerBundleName";
29 constexpr const char* JUMP_DIALOG_CALLER_MODULE_NAME = "interceptor_callerModuleName";
30 constexpr const char* JUMP_DIALOG_CALLER_LABEL_ID = "interceptor_callerLabelId";
31 constexpr const char* JUMP_DIALOG_TARGET_MODULE_NAME = "interceptor_targetModuleName";
32 constexpr const char* JUMP_DIALOG_TARGET_LABEL_ID = "interceptor_targetLabelId";
33 }
DoProcess(AbilityInterceptorParam param)34 ErrCode AbilityJumpInterceptor::DoProcess(AbilityInterceptorParam param)
35 {
36 if (!param.isWithUI) {
37 TAG_LOGI(AAFwkTag::ABILITYMGR, "This startup is not foreground, keep going.");
38 return ERR_OK;
39 }
40 bool isStartIncludeAtomicService = AbilityUtil::IsStartIncludeAtomicService(param.want, param.userId);
41 if (isStartIncludeAtomicService) {
42 TAG_LOGI(AAFwkTag::ABILITYMGR, "This startup contain atomic service, keep going.");
43 return ERR_OK;
44 }
45 // get bms
46 auto bundleMgrHelper = AbilityUtil::GetBundleManagerHelper();
47 if (bundleMgrHelper == nullptr) {
48 TAG_LOGE(AAFwkTag::ABILITYMGR, "The bundleMgrHelper is nullptr.");
49 return ERR_OK;
50 }
51 AppExecFwk::AbilityInfo targetAbilityInfo;
52 if (StartAbilityUtils::startAbilityInfo != nullptr &&
53 StartAbilityUtils::startAbilityInfo->abilityInfo.bundleName == param.want.GetBundle() &&
54 StartAbilityUtils::startAbilityInfo->abilityInfo.name == param.want.GetElement().GetAbilityName()) {
55 targetAbilityInfo = StartAbilityUtils::startAbilityInfo->abilityInfo;
56 } else {
57 IN_PROCESS_CALL_WITHOUT_RET(bundleMgrHelper->QueryAbilityInfo(param.want,
58 AppExecFwk::AbilityInfoFlag::GET_ABILITY_INFO_WITH_APPLICATION, param.userId, targetAbilityInfo));
59 }
60 if (targetAbilityInfo.type != AppExecFwk::AbilityType::PAGE) {
61 TAG_LOGI(AAFwkTag::ABILITYMGR,
62 "Target is not page Ability, keep going, abilityType:%{public}d.", targetAbilityInfo.type);
63 return ERR_OK;
64 }
65 AppExecFwk::AppJumpControlRule controlRule;
66 if (CheckControl(bundleMgrHelper, param.want, param.userId, controlRule)) {
67 #ifdef SUPPORT_GRAPHICS
68 TAG_LOGI(AAFwkTag::ABILITYMGR, "app jump need to be intercepted, caller:%{public}s, target:%{public}s",
69 controlRule.callerPkg.c_str(), controlRule.targetPkg.c_str());
70 auto sysDialogScheduler = DelayedSingleton<SystemDialogScheduler>::GetInstance();
71 Want targetWant = param.want;
72 Want dialogWant = sysDialogScheduler->GetJumpInterceptorDialogWant(targetWant);
73 AbilityUtil::ParseJumpInterceptorWant(dialogWant, controlRule.callerPkg);
74 LoadAppLabelInfo(dialogWant, controlRule, param.userId);
75 int ret = IN_PROCESS_CALL(AbilityManagerClient::GetInstance()->StartAbility(dialogWant,
76 param.requestCode, param.userId));
77 if (ret != ERR_OK) {
78 TAG_LOGI(AAFwkTag::ABILITYMGR, "appInterceptor Dialog StartAbility error, ret:%{public}d", ret);
79 return ret;
80 }
81 #endif
82 return ERR_APP_JUMP_INTERCEPTOR_STATUS;
83 }
84 return ERR_OK;
85 }
86
CheckControl(std::shared_ptr<AppExecFwk::BundleMgrHelper> & bundleMgrHelper,const Want & want,int32_t userId,AppExecFwk::AppJumpControlRule & controlRule)87 bool AbilityJumpInterceptor::CheckControl(std::shared_ptr<AppExecFwk::BundleMgrHelper> &bundleMgrHelper,
88 const Want &want, int32_t userId, AppExecFwk::AppJumpControlRule &controlRule)
89 {
90 HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__);
91 int callerUid = IPCSkeleton::GetCallingUid();
92 std::string callerBundleName;
93 auto result = IN_PROCESS_CALL(bundleMgrHelper->GetNameForUid(callerUid, callerBundleName));
94 std::string targetBundleName = want.GetBundle();
95 controlRule.callerPkg = callerBundleName;
96 controlRule.targetPkg = targetBundleName;
97 if (result != ERR_OK) {
98 TAG_LOGE(AAFwkTag::ABILITYMGR, "GetBundleName from bms fail.");
99 return false;
100 }
101 if (controlRule.callerPkg.empty() || controlRule.targetPkg.empty()) {
102 TAG_LOGI(AAFwkTag::ABILITYMGR, "This startup is not explicitly, keep going.");
103 return false;
104 }
105 if (controlRule.callerPkg == controlRule.targetPkg) {
106 TAG_LOGI(AAFwkTag::ABILITYMGR, "Jump within the same app.");
107 return false;
108 }
109 if (CheckIfJumpExempt(controlRule, userId)) {
110 TAG_LOGI(AAFwkTag::ABILITYMGR, "Jump from or to system or exempt apps.");
111 return false;
112 }
113 // get disposed status
114 auto appControlMgr = bundleMgrHelper->GetAppControlProxy();
115 if (appControlMgr == nullptr) {
116 TAG_LOGE(AAFwkTag::ABILITYMGR, "Get appControlMgr failed.");
117 return false;
118 }
119
120 if (IN_PROCESS_CALL(appControlMgr->GetAppJumpControlRule(callerBundleName, targetBundleName,
121 userId, controlRule)) != ERR_OK) {
122 TAG_LOGI(AAFwkTag::ABILITYMGR, "No jump control rule found.");
123 return true;
124 }
125 TAG_LOGI(AAFwkTag::ABILITYMGR, "Get appJumpControlRule, jumpMode:%d.", controlRule.jumpMode);
126 return controlRule.jumpMode != AppExecFwk::AbilityJumpMode::DIRECT;
127 }
128
CheckIfJumpExempt(AppExecFwk::AppJumpControlRule & controlRule,int32_t userId)129 bool AbilityJumpInterceptor::CheckIfJumpExempt(AppExecFwk::AppJumpControlRule &controlRule, int32_t userId)
130 {
131 if (CheckIfExemptByBundleName(controlRule.callerPkg,
132 PermissionConstants::PERMISSION_EXEMPT_AS_CALLER, userId)) {
133 TAG_LOGI(AAFwkTag::ABILITYMGR, "Jump from exempt caller app, No need to intercept.");
134 return true;
135 }
136 if (CheckIfExemptByBundleName(controlRule.targetPkg,
137 PermissionConstants::PERMISSION_EXEMPT_AS_TARGET, userId)) {
138 TAG_LOGI(AAFwkTag::ABILITYMGR, "Jump to exempt target app, No need to intercept.");
139 return true;
140 }
141 TAG_LOGI(AAFwkTag::ABILITYMGR, "Third-party apps jump to third-party apps.");
142 return false;
143 }
144
CheckIfExemptByBundleName(const std::string & bundleName,const std::string & permission,int32_t userId)145 bool AbilityJumpInterceptor::CheckIfExemptByBundleName(const std::string &bundleName,
146 const std::string &permission, int32_t userId)
147 {
148 HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__);
149 AppExecFwk::ApplicationInfo appInfo;
150 if (!StartAbilityUtils::GetApplicationInfo(bundleName, userId, appInfo)) {
151 TAG_LOGE(AAFwkTag::ABILITYMGR, "failed to get application info.");
152 return false;
153 }
154
155 if (appInfo.isSystemApp) {
156 TAG_LOGI(AAFwkTag::ABILITYMGR, "Bundle:%{public}s is system app.", bundleName.c_str());
157 return true;
158 }
159 int32_t ret = Security::AccessToken::AccessTokenKit::VerifyAccessToken(appInfo.accessTokenId, permission, false);
160 if (ret == Security::AccessToken::PermissionState::PERMISSION_DENIED) {
161 TAG_LOGD(AAFwkTag::ABILITYMGR, "VerifyPermission %{public}d: PERMISSION_DENIED.", appInfo.accessTokenId);
162 return false;
163 }
164 TAG_LOGI(AAFwkTag::ABILITYMGR,
165 "Bundle:%{public}s verify permission:%{public}s successed.", bundleName.c_str(), permission.c_str());
166 return true;
167 }
168
LoadAppLabelInfo(Want & want,AppExecFwk::AppJumpControlRule & controlRule,int32_t userId)169 bool AbilityJumpInterceptor::LoadAppLabelInfo(Want &want,
170 AppExecFwk::AppJumpControlRule &controlRule, int32_t userId)
171 {
172 HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__);
173 AppExecFwk::ApplicationInfo callerAppInfo;
174 StartAbilityUtils::GetApplicationInfo(controlRule.callerPkg, userId, callerAppInfo);
175 AppExecFwk::ApplicationInfo targetAppInfo;
176 StartAbilityUtils::GetApplicationInfo(controlRule.targetPkg, userId, callerAppInfo);
177 want.SetParam(JUMP_DIALOG_CALLER_BUNDLE_NAME, controlRule.callerPkg);
178 want.SetParam(JUMP_DIALOG_CALLER_MODULE_NAME, callerAppInfo.labelResource.moduleName);
179 want.SetParam(JUMP_DIALOG_CALLER_LABEL_ID, static_cast<long long>(callerAppInfo.labelId));
180 want.SetParam(JUMP_DIALOG_TARGET_MODULE_NAME, targetAppInfo.labelResource.moduleName);
181 want.SetParam(JUMP_DIALOG_TARGET_LABEL_ID, static_cast<long long>(targetAppInfo.labelId));
182 return true;
183 }
184 } // namespace AAFwk
185 } // namespace OHOS