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