1 /*
2  * Copyright (c) 2020 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_installer.h"
17 
18 #include <climits>
19 #include <sys/stat.h>
20 #include <unistd.h>
21 
22 #include "adapter.h"
23 #include "appexecfwk_errors.h"
24 #include "bundle_daemon_client.h"
25 #include "bundle_extractor.h"
26 #include "bundle_info_utils.h"
27 #include "bundle_manager_service.h"
28 #include "bundle_parser.h"
29 #include "bundle_res_transform.h"
30 #include "bundle_util.h"
31 #include "bundle_log.h"
32 #include "utils.h"
33 
34 namespace OHOS {
35 const char MATCHED_ALL_STR[] = ".*";
36 const char DELIMITER[] = "_";
37 #ifdef OHOS_DEBUG
38 const char APPID[] = "appId";
39 #endif
40 const uint8_t RAND_NUM = 16;
41 
BundleInstaller(const std::string & codeDirPath,const std::string & dataDirPath)42 BundleInstaller::BundleInstaller(const std::string &codeDirPath, const std::string &dataDirPath)
43 {
44     HILOG_INFO(HILOG_MODULE_APP, "create BundleInstaller instance!");
45     codeDirPath_ = codeDirPath;
46     dataDirPath_ = dataDirPath;
47 }
48 
~BundleInstaller()49 BundleInstaller::~BundleInstaller()
50 {
51     HILOG_INFO(HILOG_MODULE_APP, "destroy BundleInstaller instance!");
52     codeDirPath_.clear();
53     dataDirPath_.clear();
54 }
55 
GetCodeDirPath() const56 std::string BundleInstaller::GetCodeDirPath() const
57 {
58     return codeDirPath_;
59 }
60 
GetDataDirPath() const61 std::string BundleInstaller::GetDataDirPath() const
62 {
63     return dataDirPath_;
64 }
65 
ModifyInstallDirByHapType(const InstallParam & installParam,uint8_t hapType)66 void BundleInstaller::ModifyInstallDirByHapType(const InstallParam &installParam, uint8_t hapType)
67 {
68     if (hapType != THIRD_APP_FLAG) {
69         dataDirPath_ = DATA_PATH;
70         codeDirPath_ = INSTALL_PATH;
71     } else if (ManagerService::GetInstance().IsExternalInstallMode() ||
72         installParam.installLocation == INSTALL_LOCATION_PREFER_EXTERNAL) {
73         dataDirPath_ = EXTEANAL_DATA_PATH;
74         codeDirPath_ = EXTEANAL_INSTALL_PATH;
75     } else {
76         dataDirPath_ = DATA_PATH;
77         codeDirPath_ = INSTALL_PATH;
78     }
79 }
80 
RestoreInstallEnv(const InstallParam & installParam)81 void BundleInstaller::RestoreInstallEnv(const InstallParam &installParam)
82 {
83     if (ManagerService::GetInstance().IsExternalInstallMode()) {
84         return;
85     }
86 
87     if (installParam.installLocation == INSTALL_LOCATION_PREFER_EXTERNAL) {
88         dataDirPath_ = DATA_PATH;
89         codeDirPath_ = INSTALL_PATH;
90     }
91 }
92 
GetHapType(const char * path)93 uint8_t BundleInstaller::GetHapType(const char *path)
94 {
95     uint8_t hapType = 0;
96     if (BundleUtil::StartWith(path, SYSTEM_BUNDLE_PATH)) {
97         hapType = SYSTEM_APP_FLAG;
98     } else if (BundleUtil::StartWith(path, THIRD_SYSTEM_BUNDLE_PATH)) {
99         hapType = THIRD_SYSTEM_APP_FLAG;
100     } else {
101         hapType = THIRD_APP_FLAG;
102     }
103     return hapType;
104 }
105 
Install(const char * path,const InstallParam & installParam)106 uint8_t BundleInstaller::Install(const char *path, const InstallParam &installParam)
107 {
108     if (path == nullptr || installParam.installLocation < INSTALL_LOCATION_INTERNAL_ONLY ||
109         installParam.installLocation > INSTALL_LOCATION_PREFER_EXTERNAL) {
110         return ERR_APPEXECFWK_INSTALL_FAILED_PARAM_ERROR;
111     }
112 
113     char randStr[RAND_NUM] = { 0 };
114     BundleUtil::CreateRandStr(randStr, RAND_NUM);
115     if (strlen(randStr) == 0) {
116         HILOG_ERROR(HILOG_MODULE_APP, "create random str fail!");
117         return ERR_APPEXECFWK_INSTALL_FAILED_INTERNAL_ERROR;
118     }
119 
120     if (strlen(path) > PATH_MAX) {
121         return ERR_APPEXECFWK_INSTALL_FAILED_FILE_PATH_INVALID;
122     }
123 
124     char realPath[PATH_MAX + 1] = { 0 };
125     if (realpath(path, realPath) == nullptr) {
126         return ERR_APPEXECFWK_INSTALL_FAILED_FILE_PATH_INVALID;
127     }
128 
129     // set codeDirPath_ and dataDirPath_ according to hap path
130     uint8_t hapType = GetHapType(realPath);
131     ModifyInstallDirByHapType(installParam, hapType);
132 
133     InstallRecord installRecord = {
134         .bundleName = nullptr, .codePath = nullptr, .appId = nullptr, .versionCode = -1, .uid = INVALID_UID,
135         .gid = INVALID_GID
136     };
137 
138     uint8_t errorCode = ProcessBundleInstall(realPath, randStr, installRecord, hapType);
139     if (errorCode != ERR_OK) {
140         ManagerService::GetInstance().RecycleUid(installRecord.bundleName);
141         return errorCode;
142     }
143 
144     std::string uidTmpJsonPath = std::string(JSON_PATH) + UID_GID_MAP + randStr + JSON_SUFFIX;
145     if (!BackUpUidAndGidInfo(installRecord, uidTmpJsonPath.c_str())) {
146         HILOG_ERROR(HILOG_MODULE_APP, "backup uid and gid info fail!");
147         BundleInfo *bundleInfo = ManagerService::GetInstance().QueryBundleInfo(installRecord.bundleName);
148         CLEAR_INSTALL_ENV(bundleInfo);
149         return ERR_APPEXECFWK_INSTALL_FAILED_UID_AND_GID_BACKUP_ERROR;
150     }
151 
152     if (!RenameJsonFile(UID_GID_MAP, randStr) || !RenameJsonFile(installRecord.bundleName, randStr)) {
153         HILOG_ERROR(HILOG_MODULE_APP, "rename uid_gid_map json or record json fail!");
154         BundleInfo *bundleInfo = ManagerService::GetInstance().QueryBundleInfo(installRecord.bundleName);
155         CLEAR_INSTALL_ENV(bundleInfo);
156         return ERR_APPEXECFWK_INSTALL_FAILED_RENAME_FILE_ERROR;
157     }
158 
159     // if third system bundle, it need to record bundleName in THIRD_SYSTEM_BUNDLE_JSON
160     if (hapType == THIRD_SYSTEM_APP_FLAG && !CheckIsThirdSystemBundle(installRecord.bundleName)) {
161         RecordThirdSystemBundle(installRecord.bundleName, THIRD_SYSTEM_BUNDLE_JSON);
162     }
163 
164     RestoreInstallEnv(installParam);
165     return ERR_OK;
166 }
167 
ProcessBundleInstall(const std::string & path,const char * randStr,InstallRecord & installRecord,uint8_t hapType)168 uint8_t BundleInstaller::ProcessBundleInstall(const std::string &path, const char *randStr,
169     InstallRecord &installRecord, uint8_t hapType)
170 {
171     BundleInfo *bundleInfo = nullptr;
172     Permissions permissions = {.permNum = 0, .permissionTrans = nullptr};
173     BundleRes bundleRes = {
174         .bundleName = nullptr, .moduleDescriptionId = 0, .abilityRes = nullptr, .totalNumOfAbilityRes = 0
175     };
176     // check path
177     uint8_t errorCode = CheckInstallFileIsValid(const_cast<char *>(path.c_str()));
178     CHECK_PRO_RESULT(errorCode, bundleInfo, permissions, bundleRes.abilityRes);
179     // verify signature
180     SignatureInfo signatureInfo;
181 #ifdef OHOS_DEBUG
182     if (ManagerService::GetInstance().IsSignMode()) {
183         errorCode = HapSignVerify::VerifySignature(path, signatureInfo);
184         CHECK_PRO_RESULT(errorCode, bundleInfo, permissions, bundleRes.abilityRes);
185     }
186 #else
187     errorCode = HapSignVerify::VerifySignature(path, signatureInfo);
188     CHECK_PRO_RESULT(errorCode, bundleInfo, permissions, bundleRes.abilityRes);
189 #endif
190     // parse config.json
191     BundleParser bundleParser;
192     errorCode = bundleParser.ParseHapProfile(path, permissions, bundleRes, &bundleInfo);
193     CHECK_PRO_RESULT(errorCode, bundleInfo, permissions, bundleRes.abilityRes);
194 #ifdef OHOS_DEBUG
195     // check signatureInfo
196     if (ManagerService::GetInstance().IsSignMode()) {
197         errorCode = CheckProvisionInfoIsValid(signatureInfo, permissions, bundleInfo->bundleName);
198         CHECK_PRO_RESULT(errorCode, bundleInfo, permissions, bundleRes.abilityRes);
199         // check version and signature when in update status
200         errorCode = ReshapeAppId(bundleInfo->bundleName, signatureInfo.appId);
201         CHECK_PRO_RESULT(errorCode, bundleInfo, permissions, bundleRes.abilityRes);
202         bundleInfo->appId = Utils::Strdup(signatureInfo.appId.c_str());
203     } else {
204         bundleInfo->appId = Utils::Strdup(APPID);
205     }
206 #else
207     errorCode = CheckProvisionInfoIsValid(signatureInfo, permissions, bundleInfo->bundleName);
208     CHECK_PRO_RESULT(errorCode, bundleInfo, permissions, bundleRes.abilityRes);
209     // check version and signature when in update status
210     errorCode = ReshapeAppId(bundleInfo->bundleName, signatureInfo.appId);
211         CHECK_PRO_RESULT(errorCode, bundleInfo, permissions, bundleRes.abilityRes);
212     bundleInfo->appId = Utils::Strdup(signatureInfo.appId.c_str());
213 #endif
214     errorCode = (bundleInfo->appId == nullptr) ? ERR_APPEXECFWK_INSTALL_FAILED_INTERNAL_ERROR : ERR_OK;
215     CHECK_PRO_RESULT(errorCode, bundleInfo, permissions, bundleRes.abilityRes);
216     installRecord.bundleName = bundleInfo->bundleName;
217     installRecord.appId = bundleInfo->appId;
218     installRecord.versionCode = bundleInfo->versionCode;
219     errorCode = CheckVersionAndSignature(installRecord.bundleName, bundleInfo);
220     CHECK_PRO_RESULT(errorCode, bundleInfo, permissions, bundleRes.abilityRes);
221     std::string codePath = std::string(bundleInfo->codePath) + PATH_SEPARATOR + bundleInfo->moduleInfos[0].moduleName;
222     installRecord.codePath = bundleInfo->codePath;
223     // unzip bundle
224     std::string tmpCodePath = codePath + randStr;
225     errorCode = (BundleDaemonClient::GetInstance().ExtractHap(path.c_str(), tmpCodePath.c_str()) == EC_SUCCESS) ?
226         ERR_OK : ERR_APPEXECFWK_INSTALL_FAILED_EXTRACT_HAP_ERROR;
227     CHECK_PRO_PART_ROLLBACK(errorCode, tmpCodePath, permissions, bundleInfo, bundleRes.abilityRes);
228     // rename install path and record install infomation
229     bool isUpdate = ManagerService::GetInstance().QueryBundleInfo(installRecord.bundleName) != nullptr;
230     errorCode = HandleFileAndBackUpRecord(codePath.c_str(), randStr, installRecord, isUpdate, hapType);
231     CHECK_PRO_ROLLBACK(errorCode, permissions, bundleInfo, bundleRes.abilityRes, randStr);
232     bundleInfo->uid = installRecord.uid;
233     bundleInfo->gid = installRecord.uid;
234     // store permissions
235     errorCode = StorePermissions(installRecord.bundleName, permissions.permissionTrans, permissions.permNum,
236         isUpdate);
237     CHECK_PRO_ROLLBACK(errorCode, permissions, bundleInfo, bundleRes.abilityRes, randStr);
238     // update bundle Info
239     errorCode = UpdateBundleInfo(installRecord.appId, bundleRes, bundleInfo, isUpdate, hapType);
240     CHECK_PRO_ROLLBACK(errorCode, permissions, bundleInfo, bundleRes.abilityRes, randStr);
241     // free permissions
242     AdapterFree(permissions.permissionTrans);
243     AdapterFree(bundleRes.abilityRes);
244     return ERR_OK;
245 }
246 
ReshapeAppId(const char * bundleName,std::string & appId)247 uint8_t BundleInstaller::ReshapeAppId(const char *bundleName, std::string &appId)
248 {
249     if (bundleName == nullptr) {
250         return ERR_APPEXECFWK_INSTALL_FAILED_INTERNAL_ERROR;
251     }
252     size_t index = appId.find_first_of(DELIMITER);
253     if (index == std::string::npos) {
254         return ERR_APPEXECFWK_INSTALL_FAILED_INVALID_PROVISIONINFO;
255     }
256     appId = appId.replace(appId.begin(), appId.begin() + index, bundleName);
257     if (appId.empty()) {
258         HILOG_ERROR(HILOG_MODULE_APP, "appId is empty!");
259         return ERR_APPEXECFWK_INSTALL_FAILED_INTERNAL_ERROR;
260     }
261     return ERR_OK;
262 }
263 
CheckProvisionInfoIsValid(const SignatureInfo & signatureInfo,const Permissions & permissions,const char * bundleName)264 uint8_t BundleInstaller::CheckProvisionInfoIsValid(const SignatureInfo &signatureInfo, const Permissions &permissions,
265     const char *bundleName)
266 {
267     if (bundleName == nullptr || signatureInfo.provisionBundleName.empty()) {
268         return ERR_APPEXECFWK_INSTALL_FAILED_INTERNAL_ERROR;
269     }
270 
271     if (!MatchBundleName(bundleName, signatureInfo.provisionBundleName.c_str())) {
272         return ERR_APPEXECFWK_INSTALL_FAILED_INVALID_PROVISIONINFO;
273     }
274 
275     if (!MatchPermissions(signatureInfo.restrictedPermissions, permissions.permissionTrans, permissions.permNum)) {
276         return ERR_APPEXECFWK_INSTALL_FAILED_INVALID_PROVISIONINFO;
277     }
278     return ERR_OK;
279 }
280 
MatchBundleName(const char * bundleName,const char * matchedBundleName)281 bool BundleInstaller::MatchBundleName(const char *bundleName, const char *matchedBundleName)
282 {
283     if (bundleName == nullptr || matchedBundleName == nullptr) {
284         return false;
285     }
286 
287     if (strcmp(matchedBundleName, MATCHED_ALL_STR) == 0 || strcmp(bundleName, matchedBundleName) == 0) {
288         return true;
289     }
290 
291     char *pos = const_cast<char *>(matchedBundleName);
292     for (uint32_t i = 0; matchedBundleName[i] != '\0' && bundleName[i] != '\0'; i++, pos++) {
293         if (bundleName[i] != matchedBundleName[i]) {
294             if (strcmp(pos, MATCHED_ALL_STR) == 0) {
295                 return true;
296             }
297             HILOG_WARN(HILOG_MODULE_APP, "provisionBundleName is not match the bundleName!");
298             return false;
299         } else if (strcmp(pos, MATCHED_ALL_STR) == 0) {
300             return true;
301         }
302     }
303     HILOG_WARN(HILOG_MODULE_APP, "provisionBundleName is not match the bundleName!");
304     return false;
305 }
306 
MatchPermissions(const std::vector<std::string> & restrictedPermissions,PermissionTrans * permissionsTrans,int32_t permTransNum)307 bool BundleInstaller::MatchPermissions(const std::vector<std::string> & restrictedPermissions,
308     PermissionTrans *permissionsTrans, int32_t permTransNum)
309 {
310     if (permTransNum == 0) {
311         return true;
312     }
313 
314     if (permissionsTrans == nullptr) {
315         HILOG_ERROR(HILOG_MODULE_APP, "permissionsTrans is nullptr!");
316         return false;
317     }
318 
319     std::vector<std::string> realRestrictedPermissions;
320     for (int32_t i = 0; i < permTransNum; i++) {
321         if (IsPermissionRestricted((permissionsTrans + i)->name) == 0) {
322             realRestrictedPermissions.emplace_back(std::string((permissionsTrans + i)->name));
323         }
324     }
325 
326     if (realRestrictedPermissions.empty()) {
327         HILOG_INFO(HILOG_MODULE_APP, "this app has no restricted permissions!");
328         return true;
329     }
330 
331     int32_t size = realRestrictedPermissions.size();
332     for (int32_t i = 0; i < size; i++) {
333         bool isMatched = std::any_of(restrictedPermissions.begin(), restrictedPermissions.end(),
334             [realRestrictedPermissions, i](const auto & restrictedPermission)->bool {
335                 return realRestrictedPermissions[i] == restrictedPermission;
336         });
337         if (!isMatched) {
338             HILOG_WARN(HILOG_MODULE_APP, "provisionPermissions is not match the bundle reqPermissions!");
339             return false;
340         }
341     }
342     return true;
343 }
344 
HandleFileAndBackUpRecord(const char * codePath,const char * randStr,InstallRecord & record,bool isUpdate,uint8_t hapType)345 uint8_t BundleInstaller::HandleFileAndBackUpRecord(const char *codePath, const char *randStr, InstallRecord &record,
346     bool isUpdate, uint8_t hapType)
347 {
348     if (codePath == nullptr || randStr == nullptr) {
349         HILOG_ERROR(HILOG_MODULE_APP, "param is nullptr!");
350         return ERR_APPEXECFWK_INSTALL_FAILED_INTERNAL_ERROR;
351     }
352     // get ams interface
353     AmsInnerInterface *amsInterface = nullptr;
354     if (!ManagerService::GetAmsInterface(&amsInterface) || amsInterface == nullptr) {
355         HILOG_ERROR(HILOG_MODULE_APP, "get ams interface fail when install!");
356         return ERR_APPEXECFWK_INSTALL_FAILED_INTERNAL_ERROR;
357     }
358     // kill app process
359     amsInterface->TerminateApp(record.bundleName);
360     std::string tmpPath = std::string(codePath) + randStr;
361     if (BundleDaemonClient::GetInstance().RenameFile(tmpPath.c_str(), codePath) != EC_SUCCESS) {
362         BundleDaemonClient::GetInstance().RemoveFile(tmpPath.c_str());
363         return ERR_APPEXECFWK_INSTALL_FAILED_RENAME_DIR_ERROR;
364     }
365 
366     if (!isUpdate) {
367         // distribute uid for installing application
368         record.uid = ManagerService::GetInstance().GenerateUid(record.bundleName, hapType);
369         record.gid = record.uid;
370         bool isChown = ((record.uid != INVALID_UID) && (record.gid != INVALID_GID));
371         std::string dataPath = dataDirPath_ + PATH_SEPARATOR + record.bundleName;
372         if (BundleDaemonClient::GetInstance().CreateDataDirectory(
373             dataPath.c_str(), record.uid, record.gid, isChown) != EC_SUCCESS) {
374             HILOG_ERROR(HILOG_MODULE_APP, "Create data directory fail");
375             return ERR_APPEXECFWK_INSTALL_FAILED_CREATE_DATA_DIR_ERROR;
376         }
377     } else {
378         BundleInfo *bundleInfo = ManagerService::GetInstance().QueryBundleInfo(record.bundleName);
379         if (bundleInfo == nullptr) {
380             HILOG_ERROR(HILOG_MODULE_APP, "bundleInfo is nullptr when query bundleInfo!");
381             return ERR_APPEXECFWK_INSTALL_FAILED_INTERNAL_ERROR;
382         }
383         record.uid = bundleInfo->uid;
384         record.gid = bundleInfo->gid;
385     }
386     std::string bundleTmpJsonPath = std::string(JSON_PATH) + record.bundleName + randStr + JSON_SUFFIX;
387     if (!BackUpInstallRecord(record, bundleTmpJsonPath.c_str())) {
388         return ERR_APPEXECFWK_INSTALL_FAILED_RECORD_INFO_ERROR;
389     }
390     return ERR_OK;
391 }
392 
UpdateBundleInfo(const char * appId,const BundleRes & bundleRes,BundleInfo * bundleInfo,bool isUpdate,uint8_t hapType)393 uint8_t BundleInstaller::UpdateBundleInfo(const char *appId, const BundleRes &bundleRes, BundleInfo *bundleInfo,
394     bool isUpdate, uint8_t hapType)
395 {
396     if ((appId == nullptr) || (bundleInfo == nullptr)) {
397         return ERR_APPEXECFWK_OBJECT_NULL;
398     }
399     uint8_t errorCode = BundleResTransform::ConvertResInfoToBundleInfo(bundleInfo->codePath, bundleRes, bundleInfo);
400     if (errorCode != ERR_OK) {
401         return errorCode;
402     }
403     if (!isUpdate) {
404         bundleInfo->isSystemApp = (hapType == SYSTEM_APP_FLAG);
405     } else {
406         BundleInfo *oldBundleInfo = ManagerService::GetInstance().QueryBundleInfo(bundleInfo->bundleName);
407         if (oldBundleInfo == nullptr) {
408             HILOG_ERROR(HILOG_MODULE_APP, "query bundleInfo which is exists fail!");
409             return ERR_APPEXECFWK_INSTALL_FAILED_INTERNAL_ERROR;
410         }
411         bundleInfo->isSystemApp = oldBundleInfo->isSystemApp;
412     }
413     bundleInfo->appId = Utils::Strdup(appId);
414     if (bundleInfo->appId == nullptr) {
415         HILOG_ERROR(HILOG_MODULE_APP, "add appId to bundleInfo fail!");
416         ManagerService::GetInstance().RemoveBundleInfo(bundleInfo->bundleName);
417         return ERR_APPEXECFWK_INSTALL_FAILED_INTERNAL_ERROR;
418     }
419     if (!ManagerService::GetInstance().UpdateBundleInfo(bundleInfo)) {
420         return ERR_APPEXECFWK_INSTALL_FAILED_INTERNAL_ERROR;
421     }
422     return ERR_OK;
423 }
424 
Uninstall(const char * bundleName,const InstallParam & installParam)425 uint8_t BundleInstaller::Uninstall(const char *bundleName, const InstallParam &installParam)
426 {
427     if (bundleName == nullptr) {
428         return ERR_APPEXECFWK_UNINSTALL_FAILED_PARAM_ERROR;
429     }
430 
431     BundleInfo *bundleInfo = ManagerService::GetInstance().QueryBundleInfo(bundleName);
432     if (bundleInfo == nullptr) {
433         return ERR_APPEXECFWK_UNINSTALL_FAILED_BUNDLE_NOT_EXISTS;
434     }
435 
436     if (bundleInfo->isSystemApp) {
437         return ERR_APPEXECFWK_UNINSTALL_FAILED_BUNDLE_NOT_UNINSTALLABLE;
438     }
439 
440     // get ams interface
441     AmsInnerInterface *amsInterface = nullptr;
442     if (!ManagerService::GetAmsInterface(&amsInterface) || amsInterface == nullptr) {
443         HILOG_ERROR(HILOG_MODULE_APP, "get ams interface fail when uninstall!");
444         return ERR_APPEXECFWK_UNINSTALL_FAILED_INTERNAL_ERROR;
445     }
446     // kill app process
447     amsInterface->TerminateApp(bundleName);
448 
449     if (BundleDaemonClient::GetInstance().RemoveInstallDirectory(
450         bundleInfo->codePath, bundleInfo->dataPath, installParam.keepData) != EC_SUCCESS) {
451         ManagerService::GetInstance().RemoveBundleInfo(bundleName);
452         return ERR_APPEXECFWK_UNINSTALL_FAILED_DELETE_DIRS_ERROR;
453     }
454 
455     ManagerService::GetInstance().RemoveBundleInfo(bundleName);
456 
457     if (DeletePermissions(const_cast<char *>(bundleName)) < 0) {
458         return ERR_APPEXECFWK_UNINSTALL_FAILED_DELETE_PERMISSIONS_ERROR;
459     }
460 
461     // delete uid and gid info
462     if (!BundleUtil::DeleteUidInfoFromJson(bundleName)) {
463         return ERR_APPEXECFWK_UNINSTALL_FAILED_DELETE_UID_INFO_ERROR;
464     }
465 
466     std::string bundleJsonPath = std::string(JSON_PATH) + bundleName + JSON_SUFFIX;
467     if (BundleDaemonClient::GetInstance().RemoveFile(bundleJsonPath.c_str()) != EC_SUCCESS) {
468         return ERR_APPEXECFWK_UNINSTALL_FAILED_DELETE_RECORD_INFO_ERROR;
469     }
470 
471     if (CheckIsThirdSystemBundle(bundleName)) {
472         RecordThirdSystemBundle(bundleName, UNINSTALL_THIRD_SYSTEM_BUNDLE_JSON);
473     }
474     return ERR_OK;
475 }
476 
BackUpUidAndGidInfo(const InstallRecord & record,const char * jsonPath)477 bool BundleInstaller::BackUpUidAndGidInfo(const InstallRecord &record, const char *jsonPath)
478 {
479     if (jsonPath == nullptr) {
480         return false;
481     }
482     cJSON *object = BundleUtil::ConvertUidAndGidToJson(record);
483     if (object == nullptr) {
484         HILOG_ERROR(HILOG_MODULE_APP, "BackUpUidAndGidInfo fail, object is null!");
485         return false;
486     }
487 
488     char *buffer = cJSON_Print(object);
489     cJSON_Delete(object);
490     if (buffer == nullptr) {
491         return false;
492     }
493     if (BundleDaemonClient::GetInstance().StoreContentToFile(jsonPath, buffer, strlen(buffer) + 1) != EC_SUCCESS) {
494         HILOG_ERROR(HILOG_MODULE_APP, "BackUpUidAndGidInfo fail, beacuse store JsonContent fail!");
495         cJSON_free(buffer);
496         return false;
497     }
498     cJSON_free(buffer);
499     return true;
500 }
501 
CheckInstallFileIsValid(const char * path)502 uint8_t BundleInstaller::CheckInstallFileIsValid(const char *path)
503 {
504     if (path == nullptr) {
505         return ERR_APPEXECFWK_INSTALL_FAILED_PARAM_ERROR;
506     }
507 
508     if (!BundleUtil::EndWith(path, INSTALL_FILE_SUFFIX)) {
509         return ERR_APPEXECFWK_INSTALL_FAILED_INVALID_FILE_NAME;
510     }
511 
512     if (!BundleUtil::IsFile(path)) {
513         return ERR_APPEXECFWK_INSTALL_FAILED_FILE_NOT_EXISTS;
514     }
515 
516     if (BundleUtil::GetFileSize(path) == 0) {
517         return ERR_APPEXECFWK_INSTALL_FAILED_BAD_FILE;
518     }
519     return ERR_OK;
520 }
521 
CheckIsThirdSystemBundle(const char * bundleName)522 bool BundleInstaller::CheckIsThirdSystemBundle(const char *bundleName)
523 {
524     if (bundleName == nullptr) {
525         return false;
526     }
527 
528     cJSON *root = BundleUtil::GetJsonStream(THIRD_SYSTEM_BUNDLE_JSON);
529     if (root == nullptr) {
530         return false;
531     }
532 
533     cJSON *son = cJSON_GetObjectItem(root, JSON_MAIN_KEY);
534     if (!cJSON_IsArray(son)) {
535         BundleDaemonClient::GetInstance().RemoveFile(THIRD_SYSTEM_BUNDLE_JSON);
536         cJSON_Delete(root);
537         return false;
538     }
539 
540     cJSON *item = nullptr;
541     cJSON_ArrayForEach(item, son) {
542         if (!cJSON_IsString(item)) {
543             cJSON_Delete(root);
544             return false;
545         }
546         if (item->valuestring != nullptr && strcmp(bundleName, item->valuestring) == 0) {
547             cJSON_Delete(root);
548             return true;
549         }
550     }
551     cJSON_Delete(root);
552     return false;
553 }
554 
RecordThirdSystemBundle(const char * bundleName,const char * path)555 void BundleInstaller::RecordThirdSystemBundle(const char *bundleName, const char *path)
556 {
557     if ((bundleName == nullptr) || (path == nullptr)) {
558         return;
559     }
560 
561     if (!BundleUtil::IsFile(path)) {
562         InitThirdSystemBundleRecord(bundleName, path);
563         return;
564     }
565     cJSON *root = BundleUtil::GetJsonStream(path);
566     if (root == nullptr) {
567         return;
568     }
569 
570     cJSON *son = cJSON_GetObjectItem(root, JSON_MAIN_KEY);
571     if (!cJSON_IsArray(son)) {
572         BundleDaemonClient::GetInstance().RemoveFile(path);
573         cJSON_Delete(root);
574         InitThirdSystemBundleRecord(bundleName, path);
575         return;
576     }
577 
578     cJSON *str = cJSON_CreateString(bundleName);
579     if (str == nullptr) {
580         cJSON_Delete(root);
581         return;
582     }
583 
584     if (!cJSON_AddItemToArray(son, str)) {
585         cJSON_Delete(str);
586         cJSON_Delete(root);
587         return;
588     }
589 
590     char *buffer = cJSON_Print(root);
591     cJSON_Delete(root);
592     if (buffer == nullptr) {
593         return;
594     }
595 
596     if (BundleDaemonClient::GetInstance().StoreContentToFile(path, buffer, strlen(buffer) + 1) != EC_SUCCESS) {
597         HILOG_ERROR(HILOG_MODULE_APP, "record third system bundle install info fail!");
598     }
599     cJSON_free(buffer);
600 }
601 
InitThirdSystemBundleRecord(const char * bundleName,const char * path)602 void BundleInstaller::InitThirdSystemBundleRecord(const char *bundleName, const char *path)
603 {
604     if (bundleName == nullptr || path == nullptr) {
605         return;
606     }
607 
608     cJSON *root = cJSON_CreateObject();
609     if (root == nullptr) {
610         return;
611     }
612 
613     cJSON *son = cJSON_CreateArray();
614     if (son == nullptr) {
615         cJSON_Delete(root);
616         return;
617     }
618 
619     if (!cJSON_AddItemToObject(root, JSON_MAIN_KEY, son)) {
620         cJSON_Delete(son);
621         cJSON_Delete(root);
622         return;
623     }
624 
625     cJSON *str = cJSON_CreateString(bundleName);
626     if (str == nullptr) {
627         cJSON_Delete(root);
628         return;
629     }
630 
631     if (!cJSON_AddItemToArray(son, str)) {
632         cJSON_Delete(str);
633         cJSON_Delete(root);
634         return;
635     }
636 
637     char *buffer = cJSON_Print(root);
638     cJSON_Delete(root);
639     if (buffer == nullptr) {
640         return;
641     }
642 
643     if (BundleDaemonClient::GetInstance().StoreContentToFile(path, buffer, strlen(buffer) + 1) != EC_SUCCESS) {
644         HILOG_ERROR(HILOG_MODULE_APP, "init Third System Bundle Record fail!");
645     }
646     cJSON_free(buffer);
647 }
648 
BackUpInstallRecord(const InstallRecord & record,const char * jsonPath)649 bool BundleInstaller::BackUpInstallRecord(const InstallRecord &record, const char *jsonPath)
650 {
651     if (jsonPath == nullptr) {
652         return false;
653     }
654     cJSON *object = BundleUtil::ConvertInstallRecordToJson(record);
655     if (object == nullptr) {
656         HILOG_ERROR(HILOG_MODULE_APP, "BackUpInstallRecord fail, beacuse convertInstallRecordToJson object is null!");
657         return false;
658     }
659 
660     char *buffer = cJSON_Print(object);
661     cJSON_Delete(object);
662     if (buffer == nullptr) {
663         return false;
664     }
665     if (BundleDaemonClient::GetInstance().StoreContentToFile(jsonPath, buffer, strlen(buffer) + 1) != EC_SUCCESS) {
666         HILOG_ERROR(HILOG_MODULE_APP, "BackUpInstallRecord fail, beacuse store Json Content fail!");
667         cJSON_free(buffer);
668         return false;
669     }
670     cJSON_free(buffer);
671     return true;
672 }
673 
StorePermissions(const char * bundleName,PermissionTrans * permissions,int32_t permNum,bool isUpdate)674 uint8_t BundleInstaller::StorePermissions(const char *bundleName, PermissionTrans *permissions, int32_t permNum,
675     bool isUpdate)
676 {
677     if (permNum == 0) {
678         if (isUpdate) {
679             int32_t ret = DeletePermissions(bundleName);
680             HILOG_INFO(HILOG_MODULE_APP, "delete permissions, result is %d", ret);
681         }
682         return ERR_OK;
683     }
684 
685     if (bundleName == nullptr || permissions == nullptr) {
686         HILOG_ERROR(HILOG_MODULE_APP, "Store permission fail when param is nullptr!");
687         return ERR_APPEXECFWK_INSTALL_FAILED_INTERNAL_ERROR;
688     }
689 
690     if (BundleDaemonClient::GetInstance().CreatePermissionDir() != EC_SUCCESS) {
691         return ERR_APPEXECFWK_INSTALL_FAILED_CREATE_PERMISSIONS_DIR_ERROR;
692     }
693 
694     if (SaveOrUpdatePermissions(const_cast<char *>(bundleName), permissions, permNum,
695         static_cast<IsUpdate>(isUpdate)) != 0) {
696         return ERR_APPEXECFWK_INSTALL_FAILED_STORE_PERMISSIONS_ERROR;
697     }
698     return ERR_OK;
699 }
700 
CheckVersionAndSignature(const char * bundleName,BundleInfo * bundleInfo)701 uint8_t BundleInstaller::CheckVersionAndSignature(const char *bundleName, BundleInfo *bundleInfo)
702 {
703     if (bundleInfo == nullptr || bundleName == nullptr) {
704         HILOG_ERROR(HILOG_MODULE_APP, "CheckVersionAndSignature fail beacuse param is nullptr!");
705         return ERR_APPEXECFWK_INSTALL_FAILED_INTERNAL_ERROR;
706     }
707     BundleInfo *oldBundleInfo = ManagerService::GetInstance().QueryBundleInfo(bundleName);
708     if (oldBundleInfo != nullptr) {
709         if (oldBundleInfo->versionCode > bundleInfo->versionCode) {
710             return ERR_APPEXECFWK_INSTALL_FAILED_VERSION_DOWNGRADE;
711         }
712         if (oldBundleInfo->appId == nullptr || bundleInfo->appId == nullptr) {
713             HILOG_ERROR(HILOG_MODULE_APP, "appid from bundleInfo is nullptr!");
714             return ERR_APPEXECFWK_INSTALL_FAILED_INTERNAL_ERROR;
715         }
716         if (strcmp(oldBundleInfo->appId, bundleInfo->appId) != 0) {
717             return ERR_APPEXECFWK_INSTALL_FAILED_INCOMPATIBLE_SIGNATURE;
718         }
719         // in this situation, it need to change codePath and dataPath
720         if (!BundleInfoUtils::SetBundleInfoCodePath(bundleInfo, oldBundleInfo->codePath) ||
721             !BundleInfoUtils::SetBundleInfoDataPath(bundleInfo, oldBundleInfo->dataPath)) {
722             HILOG_ERROR(HILOG_MODULE_APP, "when in update situation, it change codePath or dataPath fail!");
723             return ERR_APPEXECFWK_INSTALL_FAILED_INTERNAL_ERROR;
724         }
725     }
726     return ERR_OK;
727 }
728 
RenameJsonFile(const char * fileName,const char * randStr)729 bool BundleInstaller::RenameJsonFile(const char *fileName, const char *randStr)
730 {
731     if (fileName == nullptr || randStr == nullptr) {
732         return false;
733     }
734 
735     std::string tmpJsonPath = std::string(JSON_PATH) + fileName + randStr + JSON_SUFFIX;
736     std::string jsonPath = std::string(JSON_PATH) + fileName + JSON_SUFFIX;
737     if (BundleDaemonClient::GetInstance().RenameFile(tmpJsonPath.c_str(), jsonPath.c_str()) != EC_SUCCESS) {
738         return false;
739     }
740     return true;
741 }
742 } // namespace OHOS
743