1 /*
2  * Copyright (c) 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 "bundle_overlay_install_checker.h"
17 
18 #include "bundle_overlay_manager.h"
19 
20 namespace OHOS {
21 namespace AppExecFwk {
22 namespace {
23 const std::string SHARED_TYPE = "shared";
24 constexpr int32_t OVERLAY_MAXIMUM_PRIORITY = 100;
25 } // namespace
26 
CheckOverlayInstallation(std::unordered_map<std::string,InnerBundleInfo> & newInfos,int32_t userId,int32_t & overlayType)27 ErrCode BundleOverlayInstallChecker::CheckOverlayInstallation(
28     std::unordered_map<std::string, InnerBundleInfo> &newInfos, int32_t userId, int32_t &overlayType)
29 {
30     APP_LOGD("Start to check overlay installation");
31 #ifdef BUNDLE_FRAMEWORK_OVERLAY_INSTALLATION
32     if (newInfos.empty()) {
33         return ERR_BUNDLEMANAGER_OVERLAY_QUERY_FAILED_MISSING_OVERLAY_BUNDLE;
34     }
35     bool isInternalOverlayExisted = false;
36     bool isExternalOverlayExisted = false;
37     for (auto &info : newInfos) {
38         info.second.SetUserId(userId);
39         if (info.second.GetOverlayType() == NON_OVERLAY_TYPE) {
40             APP_LOGW("the hap is not overlay hap");
41             continue;
42         }
43         if (isInternalOverlayExisted && isExternalOverlayExisted) {
44             return ERR_BUNDLEMANAGER_OVERLAY_INSTALLATION_FAILED_INTERNAL_EXTERNAL_OVERLAY_EXISTED_SIMULTANEOUSLY;
45         }
46         ErrCode result = ERR_OK;
47         if (info.second.GetOverlayType() == OVERLAY_INTERNAL_BUNDLE) {
48             isInternalOverlayExisted = true;
49             result = CheckInternalBundle(newInfos, info.second);
50         }
51         if (info.second.GetOverlayType() == OVERLAY_EXTERNAL_BUNDLE) {
52             isExternalOverlayExisted = true;
53             result = CheckExternalBundle(info.second, userId);
54         }
55         if (result != ERR_OK) {
56             APP_LOGE("check overlay installation failed due to errcode %{public}d", result);
57             return result;
58         }
59     }
60     overlayType = (newInfos.begin()->second).GetOverlayType();
61     APP_LOGD("check overlay installation successfully and overlay type is %{public}d", overlayType);
62 #else
63     APP_LOGD("overlay is not supported");
64 #endif
65     return ERR_OK;
66 }
67 
CheckInternalBundle(const std::unordered_map<std::string,InnerBundleInfo> & newInfos,const InnerBundleInfo & innerBundleInfo) const68 ErrCode BundleOverlayInstallChecker::CheckInternalBundle(
69     const std::unordered_map<std::string, InnerBundleInfo> &newInfos,
70     const InnerBundleInfo &innerBundleInfo) const
71 {
72     APP_LOGD("start");
73     // 1. check hap type
74     ErrCode result = CheckHapType(innerBundleInfo);
75     if (result != ERR_OK) {
76         APP_LOGE("check hap type failed");
77         return result;
78     }
79     // 2. check bundle type
80     if ((result = CheckBundleType(innerBundleInfo)) != ERR_OK) {
81         APP_LOGE("check bundle type failed");
82         return result;
83     }
84     // 3. check module target priority range
85     const std::map<std::string, InnerModuleInfo> &innerModuleInfos = innerBundleInfo.GetInnerModuleInfos();
86     if (innerModuleInfos.empty()) {
87         APP_LOGE("no module in the overlay hap");
88         return ERR_BUNDLEMANAGER_OVERLAY_INSTALLATION_FAILED_INTERNAL_ERROR;
89     }
90     std::string moduleName = innerBundleInfo.GetCurrentModulePackage();
91     if ((result = CheckTargetPriority(innerModuleInfos.at(moduleName).targetPriority)) != ERR_OK) {
92         APP_LOGE("target priority of module is invalid");
93         return result;
94     }
95     // 4. check TargetModule with moduleName
96     std::string targetModuleName = innerModuleInfos.at(moduleName).targetModuleName;
97     if (targetModuleName == moduleName) {
98         APP_LOGE("target moduleName cannot be same with moudleName");
99         return ERR_BUNDLEMANAGER_OVERLAY_INSTALLATION_FAILED_INVALID_MODULE_NAME;
100     }
101     // 5. check target module is non-overlay hap
102     if ((result = CheckTargetModule(innerBundleInfo.GetBundleName(), targetModuleName)) != ERR_OK) {
103         return result;
104     }
105     // 6. check version code, overlay hap has same version code with non-overlay hap
106     if ((result = CheckVersionCode(newInfos, innerBundleInfo)) != ERR_OK) {
107         return result;
108     }
109     APP_LOGD("check internal overlay installation successfully");
110     return ERR_OK;
111 }
112 
CheckExternalBundle(const InnerBundleInfo & innerBundleInfo,int32_t userId) const113 ErrCode BundleOverlayInstallChecker::CheckExternalBundle(const InnerBundleInfo &innerBundleInfo, int32_t userId) const
114 {
115     APP_LOGD("start");
116     // 1. check bundle type
117     ErrCode result = CheckBundleType(innerBundleInfo);
118     if (result != ERR_OK) {
119         APP_LOGE("check bundle type failed");
120         return result;
121     }
122 
123     result = CheckHapType(innerBundleInfo);
124     if (result != ERR_OK) {
125         APP_LOGE("check hap type failed");
126         return result;
127     }
128 
129     // 2. check priority
130     // 2.1 check bundle priority range
131     // 2.2 check module priority range
132     int32_t priority = innerBundleInfo.GetTargetPriority();
133     if ((result = CheckTargetPriority(priority)) != ERR_OK) {
134         APP_LOGE("check bundle priority failed due to %{public}d", result);
135         return result;
136     }
137 
138     const std::map<std::string, InnerModuleInfo> &innerModuleInfos = innerBundleInfo.GetInnerModuleInfos();
139     if (innerModuleInfos.empty()) {
140         APP_LOGE("no module in the overlay hap");
141         return ERR_BUNDLEMANAGER_OVERLAY_INSTALLATION_FAILED_INTERNAL_ERROR;
142     }
143     std::string moduleName = innerBundleInfo.GetCurrentModulePackage();
144     priority = innerModuleInfos.at(moduleName).targetPriority;
145     if ((result = CheckTargetPriority(priority)) != ERR_OK) {
146         APP_LOGE("target priority of module is invalid");
147         return result;
148     }
149 
150     // 3. bundleName cannot be same with targetBundleName
151     if (innerBundleInfo.GetBundleName() == innerBundleInfo.GetTargetBundleName()) {
152         APP_LOGE("bundleName %{public}s is same with targetBundleName %{public}s",
153             innerBundleInfo.GetBundleName().c_str(), innerBundleInfo.GetTargetBundleName().c_str());
154         return ERR_BUNDLEMANAGER_OVERLAY_INSTALLATION_FAILED_BUNDLE_NAME_SAME_WITH_TARGET_BUNDLE_NAME;
155     }
156 
157     // 4. overlay hap should be preInstall application
158     if (!innerBundleInfo.IsPreInstallApp()) {
159         APP_LOGE("no preInstall application for external overlay installation");
160         return ERR_BUNDLEMANAGER_OVERLAY_INSTALLATION_FAILED_NO_SYSTEM_APPLICATION_FOR_EXTERNAL_OVERLAY;
161     }
162 
163     // 5. check target bundle
164     std::string targetModuleName = innerModuleInfos.at(moduleName).targetModuleName;
165     std::string fingerprint = innerBundleInfo.GetCertificateFingerprint();
166     if ((result =
167         CheckTargetBundle(innerBundleInfo.GetTargetBundleName(), targetModuleName, fingerprint, userId)) != ERR_OK) {
168         APP_LOGE("check target bundle failed");
169         return result;
170     }
171     APP_LOGD("check external overlay installation successfully");
172     return ERR_OK;
173 }
174 
CheckHapType(const InnerBundleInfo & info) const175 ErrCode BundleOverlayInstallChecker::CheckHapType(const InnerBundleInfo &info) const
176 {
177     std::string currentPackageName = info.GetCurrentModulePackage();
178     APP_LOGD("current package is %{public}s", currentPackageName.c_str());
179     if (info.GetModuleTypeByPackage(currentPackageName) != SHARED_TYPE) {
180         APP_LOGE("overlay hap only support shared entry hap in internal overlay installation");
181         return ERR_BUNDLEMANAGER_OVERLAY_INSTALLATION_FAILED_ERROR_HAP_TYPE;
182     }
183     return ERR_OK;
184 }
185 
CheckBundleType(const InnerBundleInfo & info) const186 ErrCode BundleOverlayInstallChecker::CheckBundleType(const InnerBundleInfo &info) const
187 {
188     if (info.GetEntryInstallationFree()) {
189         APP_LOGE("overlay hap cannot be service type");
190         return ERR_BUNDLEMANAGER_OVERLAY_INSTALLATION_FAILED_ERROR_BUNDLE_TYPE;
191     }
192     return ERR_OK;
193 }
194 
CheckTargetPriority(int32_t priority) const195 ErrCode BundleOverlayInstallChecker::CheckTargetPriority(int32_t priority) const
196 {
197     APP_LOGD("start");
198     if ((priority < ServiceConstants::OVERLAY_MINIMUM_PRIORITY) || (priority > OVERLAY_MAXIMUM_PRIORITY)) {
199         APP_LOGE("overlay hap has invalid module priority %{public}d", priority);
200         return ERR_BUNDLEMANAGER_OVERLAY_INSTALLATION_FAILED_INVALID_PRIORITY;
201     }
202     return ERR_OK;
203 }
204 
CheckVersionCode(const std::unordered_map<std::string,InnerBundleInfo> & newInfos,const InnerBundleInfo & info) const205 ErrCode BundleOverlayInstallChecker::CheckVersionCode(
206     const std::unordered_map<std::string, InnerBundleInfo> &newInfos,
207     const InnerBundleInfo &info) const
208 {
209     APP_LOGD("start to check version code");
210     for (const auto &innerBundleInfo : newInfos) {
211         if (!innerBundleInfo.second.isOverlayModule(innerBundleInfo.second.GetCurrentModulePackage())) {
212             return ERR_OK;
213         }
214     }
215 
216     std::string bundleName = info.GetBundleName();
217     InnerBundleInfo oldInfo;
218     ErrCode result = ERR_OK;
219     auto isExisted = BundleOverlayManager::GetInstance()->GetInnerBundleInfo(bundleName, oldInfo);
220     auto isNonOverlayHapExisted = BundleOverlayManager::GetInstance()->IsExistedNonOverlayHap(bundleName);
221     if (isExisted) {
222         if (isNonOverlayHapExisted && (info.GetVersionCode() != oldInfo.GetVersionCode())) {
223             APP_LOGE("overlay hap needs has same version code with current bundle");
224             result = ERR_BUNDLEMANAGER_OVERLAY_INSTALLATION_FAILED_INCONSISTENT_VERSION_CODE;
225         }
226     }
227     return result;
228 }
229 
CheckTargetBundle(const std::string & targetBundleName,const std::string & targetModuleName,const std::string & fingerprint,int32_t userId) const230 ErrCode BundleOverlayInstallChecker::CheckTargetBundle(const std::string &targetBundleName,
231     const std::string &targetModuleName, const std::string &fingerprint, int32_t userId) const
232 {
233     APP_LOGD("start");
234     if (targetBundleName.empty()) {
235         APP_LOGE("invalid target bundle name");
236         return ERR_BUNDLEMANAGER_OVERLAY_INSTALLATION_FAILED_INVALID_BUNDLE_NAME;
237     }
238     InnerBundleInfo oldInfo;
239     if (!BundleOverlayManager::GetInstance()->GetInnerBundleInfo(targetBundleName, oldInfo)) {
240         APP_LOGW("target bundle is not installed");
241         return ERR_OK;
242     }
243     // 1. check target bundle is not external overlay bundle
244     if (oldInfo.GetOverlayType() == OVERLAY_EXTERNAL_BUNDLE) {
245         APP_LOGE("target bundle is cannot be external overlay bundle");
246         return ERR_BUNDLEMANAGER_OVERLAY_INSTALLATION_FAILED_TARGET_BUNDLE_IS_OVERLAY_BUNDLE;
247     }
248     // 2. check target bundle is system application
249     if (!oldInfo.IsPreInstallApp()) {
250         APP_LOGE("target bundle is not preInstall application");
251         return ERR_BUNDLEMANAGER_OVERLAY_INSTALLATION_FAILED_NO_SYSTEM_APPLICATION_FOR_EXTERNAL_OVERLAY;
252     }
253 
254     // 3. check fingerprint of current bundle with target bundle
255     if (oldInfo.GetCertificateFingerprint() != fingerprint) {
256         APP_LOGE("target bundle has different fingerprint with current bundle");
257         return ERR_BUNDLEMANAGER_OVERLAY_INSTALLATION_FAILED_DIFFERENT_SIGNATURE_CERTIFICATE;
258     }
259 
260     // 4. check target module is non-overlay hap
261     auto result = CheckTargetModule(targetBundleName, targetModuleName);
262     if (result != ERR_OK) {
263         return result;
264     }
265 
266     // 5. check target bundle is not fa module
267     if (!oldInfo.GetIsNewVersion()) {
268         APP_LOGE("target bundle is not stage model");
269         return ERR_BUNDLEMANAGER_OVERLAY_INSTALLATION_FAILED_TARGET_BUNDLE_IS_NOT_STAGE_MODULE;
270     }
271     // 6. check target bundle is not service
272     if (CheckBundleType(oldInfo) != ERR_OK) {
273         APP_LOGE("target bundle is service");
274         return ERR_BUNDLEMANAGER_OVERLAY_INSTALLATION_FAILED_TARGET_BUNDLE_IS_SERVICE;
275     }
276     return ERR_OK;
277 }
278 
CheckTargetModule(const std::string & bundleName,const std::string & targetModuleName) const279 ErrCode BundleOverlayInstallChecker::CheckTargetModule(const std::string &bundleName,
280     const std::string &targetModuleName) const
281 {
282     InnerBundleInfo oldInfo;
283     if (BundleOverlayManager::GetInstance()->GetInnerBundleInfo(bundleName, oldInfo)) {
284         if (oldInfo.FindModule(targetModuleName) && oldInfo.isOverlayModule(targetModuleName)) {
285             APP_LOGE("check target module failed");
286             return ERR_BUNDLEMANAGER_OVERLAY_INSTALLATION_FAILED_TARGET_MODULE_IS_OVERLAY_MODULE;
287         }
288     }
289     return ERR_OK;
290 }
291 
CheckOverlayUpdate(const InnerBundleInfo & oldInfo,const InnerBundleInfo & newInfo,int32_t userId) const292 ErrCode BundleOverlayInstallChecker::CheckOverlayUpdate(const InnerBundleInfo &oldInfo, const InnerBundleInfo &newInfo,
293     int32_t userId) const
294 {
295 #ifdef BUNDLE_FRAMEWORK_OVERLAY_INSTALLATION
296     if (((newInfo.GetOverlayType() == OVERLAY_EXTERNAL_BUNDLE) &&
297         (oldInfo.GetOverlayType() != OVERLAY_EXTERNAL_BUNDLE)) ||
298         ((oldInfo.GetOverlayType() == OVERLAY_EXTERNAL_BUNDLE) &&
299         (newInfo.GetOverlayType() != OVERLAY_EXTERNAL_BUNDLE))) {
300         APP_LOGE("external overlay cannot update non-external overlay application");
301         return ERR_BUNDLEMANAGER_OVERLAY_INSTALLATION_FAILED_OVERLAY_TYPE_NOT_SAME;
302     }
303 
304     std::string newModuleName = newInfo.GetCurrentModulePackage();
305     if (!oldInfo.FindModule(newModuleName)) {
306         return ERR_OK;
307     }
308     if ((newInfo.GetOverlayType() != NON_OVERLAY_TYPE) && (!oldInfo.isOverlayModule(newModuleName))) {
309         APP_LOGE("old module is non-overlay hap and new module is overlay hap");
310         return ERR_BUNDLEMANAGER_OVERLAY_INSTALLATION_FAILED_OVERLAY_TYPE_NOT_SAME;
311     }
312 
313     if ((newInfo.GetOverlayType() == NON_OVERLAY_TYPE) && (oldInfo.isOverlayModule(newModuleName))) {
314         APP_LOGE("old module is overlay hap and new module is non-overlay hap");
315         return ERR_BUNDLEMANAGER_OVERLAY_INSTALLATION_FAILED_OVERLAY_TYPE_NOT_SAME;
316     }
317 #else
318     APP_LOGD("overlay is not supported");
319 #endif
320     return ERR_OK;
321 }
322 } // AppExecFwk
323 } // OHOS