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 "inner_shared_bundle_installer.h"
17 
18 #include "app_provision_info_manager.h"
19 #include "bundle_mgr_service.h"
20 #include "installd_client.h"
21 
22 namespace OHOS {
23 namespace AppExecFwk {
24 using namespace OHOS::Security;
25 namespace {
26 const std::string HSP_VERSION_PREFIX = "v";
27 const int32_t MAX_FILE_NUMBER = 2;
28 const std::string COMPILE_SDK_TYPE_OPEN_HARMONY = "OpenHarmony";
29 const std::string DEBUG_APP_IDENTIFIER = "DEBUG_LIB_ID";
30 }
31 
InnerSharedBundleInstaller(const std::string & path)32 InnerSharedBundleInstaller::InnerSharedBundleInstaller(const std::string &path)
33     : sharedBundlePath_(path), bundleInstallChecker_(std::make_unique<BundleInstallChecker>())
34 {
35     APP_LOGI("inner shared bundle installer instance is created");
36 }
37 
~InnerSharedBundleInstaller()38 InnerSharedBundleInstaller::~InnerSharedBundleInstaller()
39 {
40     APP_LOGI("inner shared bundle installer instance is destroyed");
41     BundleUtil::DeleteTempDirs(toDeleteTempHspPath_);
42 }
43 
ParseFiles(const InstallCheckParam & checkParam)44 ErrCode InnerSharedBundleInstaller::ParseFiles(const InstallCheckParam &checkParam)
45 {
46     APP_LOGD("parsing shared bundle files, path : %{private}s", sharedBundlePath_.c_str());
47     ErrCode result = ERR_OK;
48 
49     // check file paths
50     std::vector<std::string> inBundlePaths;
51     result = BundleUtil::CheckFilePath({sharedBundlePath_}, inBundlePaths);
52     CHECK_RESULT(result, "hsp files check failed %{public}d");
53 
54     if (!checkParam.isPreInstallApp) {
55         // copy the haps to the dir which cannot be accessed from caller
56         result = CopyHspToSecurityDir(inBundlePaths);
57         CHECK_RESULT(result, "copy file failed %{public}d");
58     }
59 
60     // check number and type of the hsp and sig files
61     std::vector<std::string> bundlePaths;
62     result = ObtainHspFileAndSignatureFilePath(inBundlePaths, bundlePaths, signatureFileDir_);
63     CHECK_RESULT(result, "obtain hsp file path or signature file path failed due to %{public}d");
64 
65     // check syscap
66     result = bundleInstallChecker_->CheckSysCap(bundlePaths);
67     CHECK_RESULT(result, "hap syscap check failed %{public}d");
68 
69     // verify signature info for all haps
70     std::vector<Security::Verify::HapVerifyResult> hapVerifyResults;
71     result = bundleInstallChecker_->CheckMultipleHapsSignInfo(bundlePaths, hapVerifyResults);
72     CHECK_RESULT(result, "hap files check signature info failed %{public}d");
73 
74     // parse bundle infos
75     result = bundleInstallChecker_->ParseHapFiles(bundlePaths, checkParam, hapVerifyResults, parsedBundles_);
76     CHECK_RESULT(result, "parse haps file failed %{public}d");
77 
78     // check install permission
79     result = bundleInstallChecker_->CheckInstallPermission(checkParam, hapVerifyResults);
80     CHECK_RESULT(result, "check install permission failed %{public}d");
81 
82     // check hsp install condition
83     result = bundleInstallChecker_->CheckHspInstallCondition(hapVerifyResults);
84     CHECK_RESULT(result, "check hsp install condition failed %{public}d");
85 
86     // to send notify of start install shared application
87     sendStartSharedBundleInstallNotify(checkParam, parsedBundles_);
88 
89     // check device type
90     result = bundleInstallChecker_->CheckDeviceType(parsedBundles_);
91     CHECK_RESULT(result, "check device type failed %{public}d");
92 
93     // check label info
94     result = CheckAppLabelInfo();
95     CHECK_RESULT(result, "check label info failed %{public}d");
96 
97     // delivery sign profile to code signature
98     result = DeliveryProfileToCodeSign(hapVerifyResults);
99     CHECK_RESULT(result, "delivery sign profile failed %{public}d");
100 
101     // check native file
102     result = bundleInstallChecker_->CheckMultiNativeFile(parsedBundles_);
103     CHECK_RESULT(result, "native so is incompatible in all haps %{public}d");
104 
105     // check enterprise bundle
106     /* At this place, hapVerifyResults cannot be empty and unnecessary to check it */
107     isEnterpriseBundle_ = bundleInstallChecker_->CheckEnterpriseBundle(hapVerifyResults[0]);
108     appIdentifier_ = (hapVerifyResults[0].GetProvisionInfo().type == Security::Verify::ProvisionType::DEBUG) ?
109         DEBUG_APP_IDENTIFIER : hapVerifyResults[0].GetProvisionInfo().bundleInfo.appIdentifier;
110     compileSdkType_ = parsedBundles_.empty() ? COMPILE_SDK_TYPE_OPEN_HARMONY :
111         (parsedBundles_.begin()->second).GetBaseApplicationInfo().compileSdkType;
112     AddAppProvisionInfo(bundleName_, hapVerifyResults[0].GetProvisionInfo());
113     return result;
114 }
115 
sendStartSharedBundleInstallNotify(const InstallCheckParam & installCheckParam,const std::unordered_map<std::string,InnerBundleInfo> & infos)116 void InnerSharedBundleInstaller::sendStartSharedBundleInstallNotify(const InstallCheckParam &installCheckParam,
117     const std::unordered_map<std::string, InnerBundleInfo> &infos)
118 {
119     if (!installCheckParam.needSendEvent) {
120         APP_LOGW("sendStartSharedBundleInstallNotify needSendEvent is false");
121         return;
122     }
123     for (auto item : infos) {
124         APP_LOGD("sendStartSharedBundleInstallNotify %{public}s  %{public}s %{public}s %{public}s",
125             item.second.GetBundleName().c_str(), item.second.GetCurModuleName().c_str(),
126             item.second.GetAppId().c_str(), item.second.GetAppIdentifier().c_str());
127         NotifyBundleEvents installRes = {
128             .bundleName = item.second.GetBundleName(),
129             .modulePackage = item.second.GetCurModuleName(),
130             .type = NotifyType::START_INSTALL,
131             .appId = item.second.GetAppId(),
132             .appIdentifier = item.second.GetAppIdentifier()
133         };
134         if (NotifyBundleStatusOfShared(installRes) != ERR_OK) {
135             APP_LOGW("notify status failed for start install");
136         }
137     }
138 }
139 
NotifyBundleStatusOfShared(const NotifyBundleEvents & installRes)140 ErrCode InnerSharedBundleInstaller::NotifyBundleStatusOfShared(const NotifyBundleEvents &installRes)
141 {
142     auto dataMgr = DelayedSingleton<BundleMgrService>::GetInstance()->GetDataMgr();
143     if (!dataMgr) {
144         APP_LOGE("Get dataMgr shared_ptr nullptr");
145         return false;
146     }
147     std::shared_ptr<BundleCommonEventMgr> commonEventMgr = std::make_shared<BundleCommonEventMgr>();
148     commonEventMgr->NotifyBundleStatus(installRes, dataMgr);
149     return ERR_OK;
150 }
151 
Install(const InstallParam & installParam)152 ErrCode InnerSharedBundleInstaller::Install(const InstallParam &installParam)
153 {
154     if (parsedBundles_.empty()) {
155         APP_LOGD("no bundle to install");
156         return ERR_OK;
157     }
158 
159     ErrCode result = ERR_OK;
160     for (auto &item : parsedBundles_) {
161         result = ExtractSharedBundles(item.first, item.second);
162         item.second.SetApplicationFlags(installParam.preinstallSourceFlag);
163         CHECK_RESULT(result, "extract shared bundles failed %{public}d");
164     }
165 
166     MergeBundleInfos();
167 
168     result = SavePreInstallInfo(installParam);
169     CHECK_RESULT(result, "save pre install info failed %{public}d");
170 
171     result = SaveBundleInfoToStorage();
172     CHECK_RESULT(result, "save bundle info to storage failed %{public}d");
173 
174     // save specifiedDistributionType and additionalInfo
175     SaveInstallParamInfo(bundleName_, installParam);
176     // check mark install finish
177     result = MarkInstallFinish();
178     if (result != ERR_OK) {
179         APP_LOGE("mark install finish failed %{public}d", result);
180         RollBack();
181         return result;
182     }
183     APP_LOGD("install shared bundle successfully: %{public}s", bundleName_.c_str());
184     return result;
185 }
186 
RollBack()187 void InnerSharedBundleInstaller::RollBack()
188 {
189     // delete created directories
190     for (auto iter = createdDirs_.crbegin(); iter != createdDirs_.crend(); ++iter) {
191         ErrCode err = InstalldClient::GetInstance()->RemoveDir(*iter);
192         if (err != ERR_OK) {
193             APP_LOGE("clean dir of %{public}s failed: %{public}s", bundleName_.c_str(), iter->c_str());
194         }
195     }
196 
197     auto dataMgr = DelayedSingleton<BundleMgrService>::GetInstance()->GetDataMgr();
198     if (dataMgr == nullptr) {
199         APP_LOGE("get dataMgr failed");
200         return;
201     }
202 
203     // rollback database
204     if (!isBundleExist_) {
205         if (dataMgr->DeleteSharedBundleInfo(bundleName_)) {
206             APP_LOGE("rollback new bundle failed : %{public}s", bundleName_.c_str());
207         }
208         if (!DelayedSingleton<AppProvisionInfoManager>::GetInstance()->DeleteAppProvisionInfo(bundleName_)) {
209             APP_LOGE("bundleName: %{public}s delete appProvisionInfo failed", bundleName_.c_str());
210         }
211         return;
212     }
213 
214     if (dataMgr->UpdateInnerBundleInfo(oldBundleInfo_)) {
215         APP_LOGE("rollback old bundle failed : %{public}s", bundleName_.c_str());
216     }
217 }
218 
CheckDependency(const Dependency & dependency) const219 bool InnerSharedBundleInstaller::CheckDependency(const Dependency &dependency) const
220 {
221     if (dependency.bundleName != bundleName_) {
222         APP_LOGE("bundle name not match : %{public}s, %{public}s", bundleName_.c_str(), dependency.bundleName.c_str());
223         return false;
224     }
225 
226     for (const auto &item : parsedBundles_) {
227         const auto bundleInfo = item.second;
228         BaseSharedBundleInfo sharedBundle;
229         bool isModuleExist = bundleInfo.GetMaxVerBaseSharedBundleInfo(dependency.moduleName, sharedBundle);
230         if (isModuleExist && dependency.versionCode <= sharedBundle.versionCode) {
231             return true;
232         }
233     }
234 
235     APP_LOGE("dependency not match");
236     return false;
237 }
238 
SendBundleSystemEvent(const EventInfo & eventTemplate) const239 void InnerSharedBundleInstaller::SendBundleSystemEvent(const EventInfo &eventTemplate) const
240 {
241     EventInfo eventInfo = eventTemplate;
242     eventInfo.bundleName = bundleName_;
243     eventInfo.versionCode = newBundleInfo_.GetBaseBundleInfo().versionCode;
244     GetInstallEventInfo(eventInfo);
245 
246     BundleEventType eventType = isBundleExist_ ? BundleEventType::UPDATE : BundleEventType::INSTALL;
247     EventReport::SendBundleSystemEvent(eventType, eventInfo);
248 }
249 
CheckAppLabelInfo()250 ErrCode InnerSharedBundleInstaller::CheckAppLabelInfo()
251 {
252     if (parsedBundles_.empty()) {
253         APP_LOGE("parsedBundles is empty");
254         return ERR_OK;
255     }
256     bundleName_ = parsedBundles_.begin()->second.GetBundleName();
257 
258     auto dataMgr = DelayedSingleton<BundleMgrService>::GetInstance()->GetDataMgr();
259     if (dataMgr == nullptr) {
260         APP_LOGE("Get dataMgr shared_ptr nullptr");
261         return ERR_APPEXECFWK_INSTALL_INTERNAL_ERROR;
262     }
263 
264     isBundleExist_ = dataMgr->FetchInnerBundleInfo(bundleName_, oldBundleInfo_);
265     if (isBundleExist_) {
266         ErrCode ret = CheckBundleTypeWithInstalledVersion();
267         CHECK_RESULT(ret, "check bundle type with installed version failed %{public}d");
268 
269         // check old InnerBundleInfo together
270         parsedBundles_.emplace(bundleName_, oldBundleInfo_);
271     } else {
272         if (parsedBundles_.begin()->second.GetApplicationBundleType() != BundleType::SHARED) {
273             APP_LOGE("installing bundle is not hsp");
274             return ERR_APPEXECFWK_INSTALL_PARAM_ERROR;
275         }
276     }
277 
278     if (isBundleExist_) {
279         parsedBundles_.erase(bundleName_);
280     }
281     return ERR_OK;
282 }
283 
CheckBundleTypeWithInstalledVersion()284 ErrCode InnerSharedBundleInstaller::CheckBundleTypeWithInstalledVersion()
285 {
286     if (oldBundleInfo_.GetApplicationBundleType() != BundleType::SHARED) {
287         APP_LOGE("old bundle is not shared");
288         return ERR_APPEXECFWK_INSTALL_COMPATIBLE_POLICY_NOT_SAME;
289     }
290 
291     for (const auto &item : parsedBundles_) {
292         auto& sharedModules = item.second.GetInnerSharedModuleInfos();
293         if (sharedModules.empty() || sharedModules.begin()->second.empty()) {
294             APP_LOGW("inner shared module infos not found (%{public}s)", item.second.GetBundleName().c_str());
295             continue;
296         }
297 
298         auto& sharedModule = sharedModules.begin()->second.front();
299         BaseSharedBundleInfo installedSharedModule;
300         if (oldBundleInfo_.GetMaxVerBaseSharedBundleInfo(sharedModule.moduleName, installedSharedModule) &&
301             installedSharedModule.versionCode > sharedModule.versionCode) {
302             APP_LOGE("installing lower version shared package");
303             return ERR_APPEXECFWK_INSTALL_VERSION_DOWNGRADE;
304         }
305     }
306     return ERR_OK;
307 }
308 
MkdirIfNotExist(const std::string & dir)309 ErrCode InnerSharedBundleInstaller::MkdirIfNotExist(const std::string &dir)
310 {
311     bool isDirExist = false;
312     ErrCode result = InstalldClient::GetInstance()->IsExistDir(dir, isDirExist);
313     CHECK_RESULT(result, "check if dir exist failed %{public}d");
314     if (!isDirExist) {
315         result = InstalldClient::GetInstance()->CreateBundleDir(dir);
316         CHECK_RESULT(result, "create dir failed %{public}d");
317         createdDirs_.emplace_back(dir);
318     }
319     return result;
320 }
321 
ExtractSharedBundles(const std::string & bundlePath,InnerBundleInfo & newInfo)322 ErrCode InnerSharedBundleInstaller::ExtractSharedBundles(const std::string &bundlePath, InnerBundleInfo &newInfo)
323 {
324     ErrCode result = ERR_OK;
325     std::string bundleDir = Constants::BUNDLE_CODE_DIR + ServiceConstants::PATH_SEPARATOR + bundleName_;
326     result = MkdirIfNotExist(bundleDir);
327     CHECK_RESULT(result, "check bundle dir failed %{public}d");
328     newInfo.SetAppCodePath(bundleDir);
329 
330     uint32_t versionCode = newInfo.GetVersionCode();
331     std::string versionDir = bundleDir + ServiceConstants::PATH_SEPARATOR + HSP_VERSION_PREFIX
332         + std::to_string(versionCode);
333     result = MkdirIfNotExist(versionDir);
334     CHECK_RESULT(result, "check version dir failed %{public}d");
335 
336     auto &moduleName = newInfo.GetInnerModuleInfos().begin()->second.moduleName;
337     std::string moduleDir = versionDir + ServiceConstants::PATH_SEPARATOR + moduleName;
338     result = MkdirIfNotExist(moduleDir);
339     CHECK_RESULT(result, "check module dir failed %{public}d");
340 
341     result = ProcessNativeLibrary(bundlePath, moduleDir, moduleName, versionDir, newInfo);
342     CHECK_RESULT(result, "ProcessNativeLibrary failed %{public}d");
343 
344     if (newInfo.IsPreInstallApp()) {
345         // preInstallApp does not need to copy hsp
346         newInfo.SetModuleHapPath(bundlePath);
347     } else {
348         // save hsp and so files to installation dir
349         std::string realHspPath = moduleDir + ServiceConstants::PATH_SEPARATOR + moduleName +
350             ServiceConstants::HSP_FILE_SUFFIX;
351         result = SaveHspToRealInstallationDir(bundlePath, moduleDir, moduleName, realHspPath);
352         CHECK_RESULT(result, "save hsp file failed %{public}d");
353         newInfo.SetModuleHapPath(realHspPath);
354     }
355     if (newInfo.IsCompressNativeLibs(moduleName)) {
356         // move so to real path
357         result = MoveSoToRealPath(moduleName, versionDir);
358         CHECK_RESULT(result, "move so to real path failed %{public}d");
359     }
360     newInfo.AddModuleSrcDir(moduleDir);
361     newInfo.AddModuleResPath(moduleDir);
362     newInfo.UpdateSharedModuleInfo();
363     return ERR_OK;
364 }
365 
UpdateInnerModuleInfo(const std::string packageName,const InnerModuleInfo & innerModuleInfo)366 void InnerSharedBundleInstaller::UpdateInnerModuleInfo(const std::string packageName,
367     const InnerModuleInfo &innerModuleInfo)
368 {
369     newBundleInfo_.ReplaceInnerModuleInfo(packageName, innerModuleInfo);
370     std::string moduleDir = std::string(Constants::BUNDLE_CODE_DIR) + ServiceConstants::PATH_SEPARATOR + bundleName_ +
371         ServiceConstants::PATH_SEPARATOR + HSP_VERSION_PREFIX + std::to_string(innerModuleInfo.versionCode) +
372         ServiceConstants::PATH_SEPARATOR + innerModuleInfo.moduleName;
373     bool isDirExist = false;
374     ErrCode result = InstalldClient::GetInstance()->IsExistDir(moduleDir, isDirExist);
375     if (isDirExist) {
376         newBundleInfo_.SetCurrentModulePackage(packageName);
377         newBundleInfo_.AddModuleSrcDir(moduleDir);
378         newBundleInfo_.AddModuleResPath(moduleDir);
379     } else {
380         APP_LOGW("update path failed %{public}s %{public}d", moduleDir.c_str(), result);
381     }
382 }
383 
MergeBundleInfos()384 void InnerSharedBundleInstaller::MergeBundleInfos()
385 {
386     auto iter = parsedBundles_.begin();
387     if (isBundleExist_) {
388         newBundleInfo_ = oldBundleInfo_;
389     } else {
390         newBundleInfo_ = iter->second;
391         ++iter;
392     }
393 
394     for (; iter != parsedBundles_.end(); ++iter) {
395         const auto &currentBundle = iter->second;
396         const auto& infos = currentBundle.GetInnerSharedModuleInfos();
397         if (infos.empty()) {
398             continue;
399         }
400 
401         const auto& innerModuleInfos = infos.begin()->second;
402         if (!innerModuleInfos.empty()) {
403             const auto& innerModuleInfo = innerModuleInfos.front();
404             newBundleInfo_.InsertInnerSharedModuleInfo(innerModuleInfo.modulePackage, innerModuleInfo);
405             UpdateInnerModuleInfo(innerModuleInfo.modulePackage, innerModuleInfo);
406         }
407         // update version
408         if (newBundleInfo_.GetBaseBundleInfo().versionCode < currentBundle.GetBaseBundleInfo().versionCode) {
409             newBundleInfo_.UpdateBaseBundleInfo(currentBundle.GetBaseBundleInfo(), false);
410             newBundleInfo_.UpdateBaseApplicationInfo(currentBundle.GetBaseApplicationInfo(), false);
411             newBundleInfo_.UpdateReleaseType(currentBundle);
412         }
413     }
414 
415     newBundleInfo_.SetBundleStatus(InnerBundleInfo::BundleStatus::ENABLED);
416     newBundleInfo_.SetHideDesktopIcon(true);
417 }
418 
SavePreInstallInfo(const InstallParam & installParam)419 ErrCode InnerSharedBundleInstaller::SavePreInstallInfo(const InstallParam &installParam)
420 {
421     if (!installParam.needSavePreInstallInfo) {
422         APP_LOGD("no need to save pre install info");
423         return ERR_OK;
424     }
425 
426     auto dataMgr = DelayedSingleton<BundleMgrService>::GetInstance()->GetDataMgr();
427     if (dataMgr == nullptr) {
428         APP_LOGE("get dataMgr failed");
429         return ERR_APPEXECFWK_INSTALL_INTERNAL_ERROR;
430     }
431 
432     PreInstallBundleInfo preInstallBundleInfo;
433     if (!dataMgr->GetPreInstallBundleInfo(bundleName_, preInstallBundleInfo)) {
434         preInstallBundleInfo.SetBundleName(bundleName_);
435     }
436     preInstallBundleInfo.SetVersionCode(newBundleInfo_.GetBaseBundleInfo().versionCode);
437     for (const auto &item : parsedBundles_) {
438         preInstallBundleInfo.AddBundlePath(item.first);
439     }
440 #ifdef USE_PRE_BUNDLE_PROFILE
441     preInstallBundleInfo.SetRemovable(installParam.removable);
442 #else
443     preInstallBundleInfo.SetRemovable(newBundleInfo_.IsRemovable());
444 #endif
445     auto applicationInfo = newBundleInfo_.GetBaseApplicationInfo();
446     newBundleInfo_.AdaptMainLauncherResourceInfo(applicationInfo);
447     preInstallBundleInfo.SetLabelId(applicationInfo.labelResource.id);
448     preInstallBundleInfo.SetIconId(applicationInfo.iconResource.id);
449     preInstallBundleInfo.SetModuleName(applicationInfo.labelResource.moduleName);
450     preInstallBundleInfo.SetSystemApp(applicationInfo.isSystemApp);
451     preInstallBundleInfo.SetBundleType(BundleType::SHARED);
452     dataMgr->SavePreInstallBundleInfo(bundleName_, preInstallBundleInfo);
453     return ERR_OK;
454 }
455 
SaveBundleInfoToStorage()456 ErrCode InnerSharedBundleInstaller::SaveBundleInfoToStorage()
457 {
458     // update install mark
459     std::string packageName;
460     newBundleInfo_.SetInstallMark(bundleName_, packageName, InstallExceptionStatus::INSTALL_FINISH);
461 
462     auto dataMgr = DelayedSingleton<BundleMgrService>::GetInstance()->GetDataMgr();
463     if (dataMgr == nullptr) {
464         APP_LOGE("get dataMgr failed");
465         return ERR_APPEXECFWK_INSTALL_INTERNAL_ERROR;
466     }
467 
468     if (isBundleExist_) {
469         if (!dataMgr->UpdateInnerBundleInfo(newBundleInfo_, false)) {
470             APP_LOGE("save bundle failed : %{public}s", bundleName_.c_str());
471             return ERR_APPEXECFWK_INSTALL_INTERNAL_ERROR;
472         }
473         return ERR_OK;
474     }
475 
476     dataMgr->UpdateBundleInstallState(bundleName_, InstallState::INSTALL_START);
477     if (!dataMgr->AddInnerBundleInfo(bundleName_, newBundleInfo_)) {
478         dataMgr->UpdateBundleInstallState(bundleName_, InstallState::INSTALL_FAIL);
479         APP_LOGE("save bundle failed : %{public}s", bundleName_.c_str());
480         return ERR_APPEXECFWK_INSTALL_INTERNAL_ERROR;
481     }
482     dataMgr->UpdateBundleInstallState(bundleName_, InstallState::INSTALL_SUCCESS);
483     return ERR_OK;
484 }
485 
GetInstallEventInfo(EventInfo & eventInfo) const486 void InnerSharedBundleInstaller::GetInstallEventInfo(EventInfo &eventInfo) const
487 {
488     APP_LOGD("GetInstallEventInfo start, bundleName:%{public}s", bundleName_.c_str());
489     eventInfo.fingerprint = newBundleInfo_.GetCertificateFingerprint();
490     eventInfo.appDistributionType = newBundleInfo_.GetAppDistributionType();
491     eventInfo.hideDesktopIcon = newBundleInfo_.IsHideDesktopIcon();
492     eventInfo.timeStamp = BundleUtil::GetCurrentTimeMs();
493 
494     // report hapPath and hashValue
495     for (const auto &info : parsedBundles_) {
496         for (const auto &innerModuleInfo : info.second.GetInnerModuleInfos()) {
497             eventInfo.filePath.push_back(innerModuleInfo.second.hapPath);
498             eventInfo.hashValue.push_back(innerModuleInfo.second.hashValue);
499         }
500     }
501 }
502 
AddAppProvisionInfo(const std::string & bundleName,const Security::Verify::ProvisionInfo & provisionInfo) const503 void InnerSharedBundleInstaller::AddAppProvisionInfo(const std::string &bundleName,
504     const Security::Verify::ProvisionInfo &provisionInfo) const
505 {
506     AppProvisionInfo appProvisionInfo = bundleInstallChecker_->ConvertToAppProvisionInfo(provisionInfo);
507     if (!DelayedSingleton<AppProvisionInfoManager>::GetInstance()->AddAppProvisionInfo(
508         bundleName, appProvisionInfo)) {
509         APP_LOGW("bundleName: %{public}s add appProvisionInfo failed", bundleName.c_str());
510     }
511 }
512 
SaveInstallParamInfo(const std::string & bundleName,const InstallParam & installParam) const513 void InnerSharedBundleInstaller::SaveInstallParamInfo(
514     const std::string &bundleName, const InstallParam &installParam) const
515 {
516     if (!installParam.specifiedDistributionType.empty()) {
517         if (!DelayedSingleton<AppProvisionInfoManager>::GetInstance()->SetSpecifiedDistributionType(
518             bundleName, installParam.specifiedDistributionType)) {
519             APP_LOGW("bundleName: %{public}s SetSpecifiedDistributionType failed", bundleName.c_str());
520         }
521     }
522     if (!installParam.additionalInfo.empty()) {
523         if (!DelayedSingleton<AppProvisionInfoManager>::GetInstance()->SetAdditionalInfo(
524             bundleName, installParam.additionalInfo)) {
525             APP_LOGW("bundleName: %{public}s SetAdditionalInfo failed", bundleName.c_str());
526         }
527     }
528 }
529 
CopyHspToSecurityDir(std::vector<std::string> & bundlePaths)530 ErrCode InnerSharedBundleInstaller::CopyHspToSecurityDir(std::vector<std::string> &bundlePaths)
531 {
532     for (size_t index = 0; index < bundlePaths.size(); ++index) {
533         auto destination = BundleUtil::CopyFileToSecurityDir(bundlePaths[index], DirType::STREAM_INSTALL_DIR,
534             toDeleteTempHspPath_);
535         if (destination.empty()) {
536             APP_LOGE("copy file %{public}s to security dir failed", bundlePaths[index].c_str());
537             return ERR_APPEXECFWK_INSTALL_COPY_HAP_FAILED;
538         }
539         bundlePaths[index] = destination;
540     }
541     return ERR_OK;
542 }
543 
ObtainHspFileAndSignatureFilePath(const std::vector<std::string> & inBundlePaths,std::vector<std::string> & bundlePaths,std::string & signatureFilePath)544 ErrCode InnerSharedBundleInstaller::ObtainHspFileAndSignatureFilePath(const std::vector<std::string> &inBundlePaths,
545     std::vector<std::string> &bundlePaths, std::string &signatureFilePath)
546 {
547     if (inBundlePaths.empty() || inBundlePaths.size() > MAX_FILE_NUMBER) {
548         APP_LOGE("number of files in single shared lib path is illegal");
549         return ERR_APPEXECFWK_INSTALL_FILE_PATH_INVALID;
550     }
551     if (inBundlePaths.size() == 1) {
552         if (!BundleUtil::EndWith(inBundlePaths[0], ServiceConstants::HSP_FILE_SUFFIX)) {
553             APP_LOGE("invalid file in shared bundle dir");
554             return ERR_APPEXECFWK_INSTALL_FILE_PATH_INVALID;
555         }
556         bundlePaths.emplace_back(inBundlePaths[0]);
557         return ERR_OK;
558     }
559     int32_t numberOfHsp = 0;
560     int32_t numberOfSignatureFile = 0;
561     for (const auto &path : inBundlePaths) {
562         if ((path.find(ServiceConstants::HSP_FILE_SUFFIX) == std::string::npos) &&
563             (path.find(ServiceConstants::CODE_SIGNATURE_FILE_SUFFIX) == std::string::npos)) {
564             APP_LOGE("only hsp or sig file can be contained in shared bundle dir");
565             return ERR_APPEXECFWK_INSTALL_FILE_PATH_INVALID;
566         }
567         if (BundleUtil::EndWith(path, ServiceConstants::HSP_FILE_SUFFIX)) {
568             numberOfHsp++;
569             bundlePaths.emplace_back(path);
570         }
571         if (BundleUtil::EndWith(path, ServiceConstants::CODE_SIGNATURE_FILE_SUFFIX)) {
572             numberOfSignatureFile++;
573             signatureFilePath = path;
574         }
575         if ((numberOfHsp >= MAX_FILE_NUMBER) || (numberOfSignatureFile >= MAX_FILE_NUMBER)) {
576             APP_LOGE("only one hsp and one signature file can be contained in a single shared bundle dir");
577             return ERR_APPEXECFWK_INSTALL_FILE_PATH_INVALID;
578         }
579     }
580     APP_LOGD("signatureFilePath is %{public}s", signatureFilePath.c_str());
581     return ERR_OK;
582 }
583 
SaveHspToRealInstallationDir(const std::string & bundlePath,const std::string & moduleDir,const std::string & moduleName,const std::string & realHspPath)584 ErrCode InnerSharedBundleInstaller::SaveHspToRealInstallationDir(const std::string &bundlePath,
585     const std::string &moduleDir,
586     const std::string &moduleName,
587     const std::string &realHspPath)
588 {
589     // 1. create temp dir
590     ErrCode result = ERR_OK;
591     std::string tempHspDir = moduleDir + ServiceConstants::PATH_SEPARATOR + moduleName;
592     result = MkdirIfNotExist(tempHspDir);
593     CHECK_RESULT(result, "create tempHspDir dir failed %{public}d");
594 
595     // 2. copy hsp to installation dir, and then to verify code signature of hsp
596     std::string tempHspPath = tempHspDir + ServiceConstants::PATH_SEPARATOR + moduleName +
597         ServiceConstants::HSP_FILE_SUFFIX;
598     if (!signatureFileDir_.empty()) {
599         result = InstalldClient::GetInstance()->CopyFile(bundlePath, tempHspPath, signatureFileDir_);
600     } else {
601         result = InstalldClient::GetInstance()->MoveHapToCodeDir(bundlePath, tempHspPath);
602         CHECK_RESULT(result, "copy hsp to install dir failed %{public}d");
603         bool isCompileSdkOpenHarmony = (compileSdkType_ == COMPILE_SDK_TYPE_OPEN_HARMONY);
604         result = VerifyCodeSignatureForHsp(tempHspPath, appIdentifier_, isEnterpriseBundle_,
605             isCompileSdkOpenHarmony, bundleName_);
606     }
607     CHECK_RESULT(result, "copy hsp to install dir failed %{public}d");
608 
609     // 3. move hsp to real installation dir
610     APP_LOGD("move file from temp path %{public}s to real path %{public}s", tempHspPath.c_str(), realHspPath.c_str());
611     result = InstalldClient::GetInstance()->MoveFile(tempHspPath, realHspPath);
612     CHECK_RESULT(result, "move hsp to install dir failed %{public}d");
613 
614     // 4. remove temp dir
615     result = InstalldClient::GetInstance()->RemoveDir(tempHspDir);
616     if (result != ERR_OK) {
617         APP_LOGW("remove temp hsp dir %{public}s failed, error is %{public}d", tempHspDir.c_str(), result);
618     }
619     return ERR_OK;
620 }
621 
MoveSoToRealPath(const std::string & moduleName,const std::string & versionDir)622 ErrCode InnerSharedBundleInstaller::MoveSoToRealPath(const std::string &moduleName, const std::string &versionDir)
623 {
624     // 1. move so files to real installation dir
625     std::string realSoPath = versionDir + ServiceConstants::PATH_SEPARATOR + nativeLibraryPath_ +
626         ServiceConstants::PATH_SEPARATOR;
627     ErrCode result = MkdirIfNotExist(realSoPath);
628     CHECK_RESULT(result, "check module dir failed %{public}d");
629 
630     std::string tempNativeLibraryPath = ObtainTempSoPath(moduleName, nativeLibraryPath_);
631     if (tempNativeLibraryPath.empty()) {
632         APP_LOGI("no so libs existed");
633         return ERR_OK;
634     }
635     std::string tempSoPath = versionDir + ServiceConstants::PATH_SEPARATOR + tempNativeLibraryPath;
636     APP_LOGD("move so files from path %{public}s to path %{public}s", tempSoPath.c_str(), realSoPath.c_str());
637     result = InstalldClient::GetInstance()->MoveFiles(tempSoPath, realSoPath);
638     if (result != ERR_OK) {
639         APP_LOGE("move file to real path failed %{public}d", result);
640         return ERR_APPEXECFWK_INSTALLD_MOVE_FILE_FAILED;
641     }
642 
643     // 2. remove so temp dir
644     std::string deleteTempDir = versionDir + ServiceConstants::PATH_SEPARATOR + moduleName
645         + ServiceConstants::TMP_SUFFIX;
646     result = InstalldClient::GetInstance()->RemoveDir(deleteTempDir);
647     if (result != ERR_OK) {
648         APP_LOGW("remove hsp temp so dir %{public}s failed, error is %{public}d", deleteTempDir.c_str(), result);
649     }
650     return ERR_OK;
651 }
652 
ObtainTempSoPath(const std::string & moduleName,const std::string & nativeLibPath)653 std::string InnerSharedBundleInstaller::ObtainTempSoPath(const std::string &moduleName,
654     const std::string &nativeLibPath)
655 {
656     std::string tempSoPath;
657     if (nativeLibPath.empty()) {
658         APP_LOGE("invalid native libs path");
659         return tempSoPath;
660     }
661     tempSoPath = nativeLibPath;
662     auto pos = tempSoPath.find(moduleName);
663     if (pos == std::string::npos) {
664         tempSoPath = moduleName + ServiceConstants::TMP_SUFFIX + ServiceConstants::PATH_SEPARATOR + tempSoPath;
665     } else {
666         std::string innerTempStr = moduleName + ServiceConstants::TMP_SUFFIX;
667         tempSoPath.replace(pos, moduleName.length(), innerTempStr);
668     }
669     return tempSoPath + ServiceConstants::PATH_SEPARATOR;
670 }
671 
ProcessNativeLibrary(const std::string & bundlePath,const std::string & moduleDir,const std::string & moduleName,const std::string & versionDir,InnerBundleInfo & newInfo)672 ErrCode InnerSharedBundleInstaller::ProcessNativeLibrary(
673     const std::string &bundlePath,
674     const std::string &moduleDir,
675     const std::string &moduleName,
676     const std::string &versionDir,
677     InnerBundleInfo &newInfo)
678 {
679     std::string cpuAbi;
680     if (!newInfo.FetchNativeSoAttrs(moduleName, cpuAbi, nativeLibraryPath_)) {
681         return ERR_OK;
682     }
683     if (newInfo.IsCompressNativeLibs(moduleName)) {
684         std::string tempNativeLibraryPath = ObtainTempSoPath(moduleName, nativeLibraryPath_);
685         if (tempNativeLibraryPath.empty()) {
686             APP_LOGE("tempNativeLibraryPath is empty");
687             return ERR_APPEXECFWK_INSTALLD_EXTRACT_FILES_FAILED;
688         }
689         std::string tempSoPath = versionDir + ServiceConstants::PATH_SEPARATOR + tempNativeLibraryPath;
690         APP_LOGD("tempSoPath=%{public}s,cpuAbi=%{public}s, bundlePath=%{public}s",
691             tempSoPath.c_str(), cpuAbi.c_str(), bundlePath.c_str());
692         auto result = InstalldClient::GetInstance()->ExtractModuleFiles(bundlePath, moduleDir, tempSoPath, cpuAbi);
693         CHECK_RESULT(result, "extract module files failed %{public}d");
694         // verify hap or hsp code signature for compressed so files
695         result = VerifyCodeSignatureForNativeFiles(
696             bundlePath, cpuAbi, tempSoPath, signatureFileDir_, newInfo.IsPreInstallApp());
697         CHECK_RESULT(result, "fail to VerifyCodeSignature, error is %{public}d");
698         cpuAbi_ = cpuAbi;
699         tempSoPath_ = tempSoPath;
700         isPreInstalledBundle_ = newInfo.IsPreInstallApp();
701     } else {
702         std::vector<std::string> fileNames;
703         auto result = InstalldClient::GetInstance()->GetNativeLibraryFileNames(bundlePath, cpuAbi, fileNames);
704         CHECK_RESULT(result, "fail to GetNativeLibraryFileNames, error is %{public}d");
705         newInfo.SetNativeLibraryFileNames(moduleName, fileNames);
706     }
707     return ERR_OK;
708 }
709 
VerifyCodeSignatureForNativeFiles(const std::string & bundlePath,const std::string & cpuAbi,const std::string & targetSoPath,const std::string & signatureFileDir,bool isPreInstalledBundle) const710 ErrCode InnerSharedBundleInstaller::VerifyCodeSignatureForNativeFiles(const std::string &bundlePath,
711     const std::string &cpuAbi, const std::string &targetSoPath, const std::string &signatureFileDir,
712     bool isPreInstalledBundle) const
713 {
714     if (!isPreInstalledBundle) {
715         APP_LOGD("not pre-install app, skip verify code signature for native files");
716         return ERR_OK;
717     }
718     APP_LOGD("begin to verify code signature for hsp native files");
719     bool isCompileSdkOpenHarmony = (compileSdkType_ == COMPILE_SDK_TYPE_OPEN_HARMONY);
720     CodeSignatureParam codeSignatureParam;
721     codeSignatureParam.modulePath = bundlePath;
722     codeSignatureParam.cpuAbi = cpuAbi;
723     codeSignatureParam.targetSoPath = targetSoPath;
724     codeSignatureParam.signatureFileDir = signatureFileDir;
725     codeSignatureParam.isEnterpriseBundle = isEnterpriseBundle_;
726     codeSignatureParam.appIdentifier = appIdentifier_;
727     codeSignatureParam.isCompileSdkOpenHarmony = isCompileSdkOpenHarmony;
728     codeSignatureParam.isPreInstalledBundle = isPreInstalledBundle;
729     return InstalldClient::GetInstance()->VerifyCodeSignature(codeSignatureParam);
730 }
731 
VerifyCodeSignatureForHsp(const std::string & tempHspPath,const std::string & appIdentifier,bool isEnterpriseBundle,bool isCompileSdkOpenHarmony,const std::string & bundleName) const732 ErrCode InnerSharedBundleInstaller::VerifyCodeSignatureForHsp(const std::string &tempHspPath,
733     const std::string &appIdentifier, bool isEnterpriseBundle, bool isCompileSdkOpenHarmony,
734     const std::string &bundleName) const
735 {
736     APP_LOGD("begin to verify code signature for hsp");
737     CodeSignatureParam codeSignatureParam;
738     codeSignatureParam.modulePath = tempHspPath;
739     codeSignatureParam.cpuAbi = cpuAbi_;
740     codeSignatureParam.targetSoPath = tempSoPath_;
741     codeSignatureParam.appIdentifier = appIdentifier;
742     codeSignatureParam.signatureFileDir = signatureFileDir_;
743     codeSignatureParam.isEnterpriseBundle = isEnterpriseBundle;
744     codeSignatureParam.isCompileSdkOpenHarmony = isCompileSdkOpenHarmony;
745     codeSignatureParam.isPreInstalledBundle = isPreInstalledBundle_;
746     return InstalldClient::GetInstance()->VerifyCodeSignatureForHap(codeSignatureParam);
747 }
748 
DeliveryProfileToCodeSign(std::vector<Security::Verify::HapVerifyResult> & hapVerifyResults) const749 ErrCode InnerSharedBundleInstaller::DeliveryProfileToCodeSign(
750     std::vector<Security::Verify::HapVerifyResult> &hapVerifyResults) const
751 {
752     if (isBundleExist_) {
753         APP_LOGD("shared bundle %{public}s has been installed and unnecessary to delivery sign profile",
754             bundleName_.c_str());
755         return ERR_OK;
756     }
757     if (hapVerifyResults.empty()) {
758         APP_LOGE("no sign info in the all haps");
759         return ERR_APPEXECFWK_INSTALL_FAILED_INCOMPATIBLE_SIGNATURE;
760     }
761 
762     Security::Verify::ProvisionInfo provisionInfo = hapVerifyResults[0].GetProvisionInfo();
763     if (provisionInfo.distributionType == Security::Verify::AppDistType::ENTERPRISE ||
764         provisionInfo.distributionType == Security::Verify::AppDistType::ENTERPRISE_NORMAL ||
765         provisionInfo.distributionType == Security::Verify::AppDistType::ENTERPRISE_MDM ||
766         provisionInfo.type == Security::Verify::ProvisionType::DEBUG) {
767         if (provisionInfo.profileBlockLength == 0 || provisionInfo.profileBlock == nullptr) {
768             APP_LOGE("invalid sign profile");
769             return ERR_APPEXECFWK_INSTALL_FAILED_INCOMPATIBLE_SIGNATURE;
770         }
771         return InstalldClient::GetInstance()->DeliverySignProfile(provisionInfo.bundleInfo.bundleName,
772             provisionInfo.profileBlockLength, provisionInfo.profileBlock.get());
773     }
774     return ERR_OK;
775 }
776 
SetCheckResultMsg(const std::string checkResultMsg) const777 void InnerSharedBundleInstaller::SetCheckResultMsg(const std::string checkResultMsg) const
778 {
779     bundleInstallChecker_->SetCheckResultMsg(checkResultMsg);
780 }
781 
MarkInstallFinish()782 ErrCode InnerSharedBundleInstaller::MarkInstallFinish()
783 {
784     auto dataMgr = DelayedSingleton<BundleMgrService>::GetInstance()->GetDataMgr();
785     if (dataMgr == nullptr) {
786         APP_LOGE("Get dataMgr shared_ptr nullptr");
787         return ERR_APPEXECFWK_INSTALL_INTERNAL_ERROR;
788     }
789     InnerBundleInfo info;
790     if (!dataMgr->FetchInnerBundleInfo(bundleName_, info)) {
791         APP_LOGE("mark finish failed, -n %{public}s not exist", bundleName_.c_str());
792         return ERR_APPEXECFWK_INSTALL_INTERNAL_ERROR;
793     }
794     info.SetBundleStatus(InnerBundleInfo::BundleStatus::ENABLED);
795     info.SetInstallMark(bundleName_, info.GetCurModuleName(), InstallExceptionStatus::INSTALL_FINISH);
796     if (!dataMgr->UpdateInnerBundleInfo(info, true)) {
797         if (!dataMgr->UpdateInnerBundleInfo(info, true)) {
798             APP_LOGE("save mark failed, -n %{public}s", bundleName_.c_str());
799             return ERR_APPEXECFWK_INSTALL_INTERNAL_ERROR;
800         }
801     }
802     return ERR_OK;
803 }
804 }  // namespace AppExecFwk
805 }  // namespace OHOS
806