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/start_other_app_interceptor.h"
17 
18 #include "ability_record.h"
19 #include "hilog_tag_wrapper.h"
20 #include "parameters.h"
21 #include "permission_verification.h"
22 #include "start_ability_utils.h"
23 #include "tokenid_kit.h"
24 
25 namespace OHOS {
26 namespace AAFwk {
27 namespace {
28 const uint32_t API_VERSION_MOD = 100;
29 const uint32_t API_SINCE_VISION = 12;
30 constexpr const char* ABILITY_SUPPORT_START_OTHER_APP = "persist.sys.abilityms.support.start_other_app";
31 constexpr const char* IS_DELEGATOR_CALL = "isDelegatorCall";
32 constexpr const char* OPEN_LINK_SCENE_IDENTIFICATION = "appLinkingOnly";
33 }
34 
DoProcess(AbilityInterceptorParam param)35 ErrCode StartOtherAppInterceptor::DoProcess(AbilityInterceptorParam param)
36 {
37     if (StartAbilityUtils::skipStartOther) {
38         StartAbilityUtils::skipStartOther = false;
39         return ERR_OK;
40     }
41     std::string supportStart = OHOS::system::GetParameter(ABILITY_SUPPORT_START_OTHER_APP, "true");
42     if (supportStart == "true") {
43         TAG_LOGD(AAFwkTag::ABILITYMGR, "Abilityms support start other app.");
44         return ERR_OK;
45     }
46 
47     if (!param.isWithUI || param.isStartAsCaller) {
48         return ERR_OK;
49     }
50     if (CheckNativeCall() || CheckCallerIsSystemApp() ||
51         (param.abilityInfo != nullptr && CheckTargetIsSystemApp(param.abilityInfo->applicationInfo))) {
52         return ERR_OK;
53     }
54 
55     if (!CheckStartOtherApp(param.want)) {
56         return ERR_OK;
57     }
58 
59     if (param.abilityInfo != nullptr && CheckAncoShellCall(param.abilityInfo->applicationInfo, param.want)) {
60         return ERR_OK;
61     }
62 
63     if (param.want.HasParameter(OPEN_LINK_SCENE_IDENTIFICATION)) {
64         return ERR_OK;
65     }
66 
67     AppExecFwk::ApplicationInfo callerApplicationInfo;
68     if (!GetApplicationInfo(param.callerToken, callerApplicationInfo)) {
69         if (IsDelegatorCall(param.want)) {
70             return ERR_OK;
71         }
72         TAG_LOGE(AAFwkTag::ABILITYMGR, "Can not find caller info");
73         return ERR_INVALID_CALLER;
74     }
75 
76     if (CheckCallerApiBelow12(callerApplicationInfo)) {
77         return ERR_OK;
78     }
79     TAG_LOGE(AAFwkTag::ABILITYMGR, "Can not start other app when api version is above 11");
80     return ERR_START_OTHER_APP_FAILED;
81 }
82 
CheckNativeCall()83 bool StartOtherAppInterceptor::CheckNativeCall()
84 {
85     auto isSaCall = AAFwk::PermissionVerification::GetInstance()->IsSACall();
86     auto isShellCall = AAFwk::PermissionVerification::GetInstance()->IsShellCall();
87     if (isSaCall || isShellCall) {
88         return true;
89     }
90     return false;
91 }
92 
CheckCallerIsSystemApp()93 bool StartOtherAppInterceptor::CheckCallerIsSystemApp()
94 {
95     auto callerToken = IPCSkeleton::GetCallingFullTokenID();
96     if (!Security::AccessToken::TokenIdKit::IsSystemAppByFullTokenID(callerToken)) {
97         return false;
98     }
99     return true;
100 }
101 
CheckTargetIsSystemApp(const AppExecFwk::ApplicationInfo & applicationInfo)102 bool StartOtherAppInterceptor::CheckTargetIsSystemApp(const AppExecFwk::ApplicationInfo &applicationInfo)
103 {
104     return applicationInfo.isSystemApp;
105 }
106 
GetApplicationInfo(const sptr<IRemoteObject> & callerToken,AppExecFwk::ApplicationInfo & applicationInfo)107 bool StartOtherAppInterceptor::GetApplicationInfo(const sptr<IRemoteObject> &callerToken,
108     AppExecFwk::ApplicationInfo &applicationInfo)
109 {
110     if (callerToken == nullptr) {
111         int32_t callerPid = IPCSkeleton::GetCallingPid();
112         auto appScheduler = DelayedSingleton<AppScheduler>::GetInstance();
113         bool debug;
114         if (appScheduler != nullptr &&
115             appScheduler->GetApplicationInfoByProcessID(callerPid, applicationInfo, debug) == ERR_OK) {
116             return true;
117         }
118         return false;
119     }
120     auto abilityRecord = Token::GetAbilityRecordByToken(callerToken);
121     if (abilityRecord == nullptr) {
122         return false;
123     }
124     applicationInfo = abilityRecord->GetApplicationInfo();
125     return true;
126 }
127 
CheckAncoShellCall(const AppExecFwk::ApplicationInfo & applicationInfo,const Want want)128 bool StartOtherAppInterceptor::CheckAncoShellCall(const AppExecFwk::ApplicationInfo &applicationInfo,
129     const Want want)
130 {
131     return (applicationInfo.codePath == std::to_string(CollaboratorType::RESERVE_TYPE) ||
132         applicationInfo.codePath == std::to_string(CollaboratorType::OTHERS_TYPE));
133 }
134 
CheckStartOtherApp(const Want want)135 bool StartOtherAppInterceptor::CheckStartOtherApp(const Want want)
136 {
137     return want.GetStringParam(Want::PARAM_RESV_CALLER_BUNDLE_NAME) != want.GetElement().GetBundleName();
138 }
139 
CheckCallerApiBelow12(const AppExecFwk::ApplicationInfo & applicationInfo)140 bool StartOtherAppInterceptor::CheckCallerApiBelow12(const AppExecFwk::ApplicationInfo &applicationInfo)
141 {
142     return (applicationInfo.apiTargetVersion % API_VERSION_MOD < API_SINCE_VISION);
143 }
144 
IsDelegatorCall(const Want want)145 bool StartOtherAppInterceptor::IsDelegatorCall(const Want want)
146 {
147     AppExecFwk::RunningProcessInfo processInfo;
148     DelayedSingleton<AppScheduler>::GetInstance()->
149         GetRunningProcessInfoByPid(IPCSkeleton::GetCallingPid(), processInfo);
150     if (processInfo.isTestProcess && want.GetBoolParam(IS_DELEGATOR_CALL, false)) {
151         return true;
152     }
153     return false;
154 }
155 }
156 }