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 "gt_bundle_installer.h"
17 #include "app_verify_pub.h"
18
19 #ifdef __cplusplus
20 extern "C" {
21 #endif
22 #ifdef __cplusplus
23 }
24 #endif
25 #include "appexecfwk_errors.h"
26 #include "bundle_util.h"
27 #include "bundlems_log.h"
28 #include "cstdio"
29 #include "dirent.h"
30 #include "fcntl.h"
31 #include "global.h"
32 #include "gt_bundle_extractor.h"
33 #include "gt_bundle_manager_service.h"
34 #include "gt_bundle_parser.h"
35 #include "sys/stat.h"
36 #include "unistd.h"
37 #include "utils.h"
38
39 namespace OHOS {
40 const char MATCHED_ALL_STR[] = ".*";
41 const uint8_t OPERATION_DOING = 200;
42 const uint8_t BMS_FIRST_FINISHED_PROCESS = 10;
43 const uint8_t BMS_SECOND_FINISHED_PROCESS = 50;
44 const uint8_t BMS_THIRD_FINISHED_PROCESS = 60;
45 const uint8_t BMS_FOURTH_FINISHED_PROCESS = 70;
46 const uint8_t BMS_FIFTH_FINISHED_PROCESS = 80;
47 const uint8_t BMS_SIXTH_FINISHED_PROCESS = 90;
48 const uint8_t RADN_NUM = 16;
49
PreCheckBundle(const char * path,int32_t & fp,SignatureInfo & signatureInfo,uint32_t & fileSize,uint8_t bundleStyle)50 uint8_t GtBundleInstaller::PreCheckBundle(const char *path, int32_t &fp, SignatureInfo &signatureInfo,
51 uint32_t &fileSize, uint8_t bundleStyle)
52 {
53 // check install file path and file whether is valid
54 if (!BundleUtil::IsFile(path)) {
55 return ERR_APPEXECFWK_INSTALL_FAILED_FILE_NOT_EXISTS;
56 }
57
58 fileSize = BundleUtil::GetFileSize(path);
59 if (fileSize == 0) {
60 return ERR_APPEXECFWK_INSTALL_FAILED_BAD_FILE;
61 }
62
63 // get fp and bundleName from install file
64 char *bundleName = nullptr;
65 uint8_t errorCode = GtBundleExtractor::ExtractBundleParam(path, fp, &bundleName);
66 if (errorCode != ERR_OK) {
67 UI_Free(bundleName);
68 return errorCode;
69 }
70
71 RefreshAllServiceTimeStamp();
72 errorCode = VerifySignature(path, signatureInfo, fileSize, bundleStyle);
73 if (errorCode != ERR_OK) {
74 UI_Free(bundleName);
75 return errorCode;
76 }
77 // reshape appId
78 if ((signatureInfo.appId != nullptr) && strstr(signatureInfo.appId, MATCHED_ALL_STR) == nullptr) {
79 if (!BundleUtil::StartWith(signatureInfo.appId, bundleName)) {
80 HILOG_ERROR(HILOG_MODULE_AAFWK, "bundleName does not match the appId!");
81 UI_Free(bundleName);
82 return ERR_APPEXECFWK_INSTALL_FAILED_INVALID_PROVISIONINFO;
83 }
84 }
85 if ((signatureInfo.appId != nullptr) && strstr(signatureInfo.appId, bundleName) == nullptr) {
86 signatureInfo.appId = ReshapeAppId(bundleName, signatureInfo.appId);
87 if (signatureInfo.appId == nullptr) {
88 UI_Free(bundleName);
89 return ERR_APPEXECFWK_INSTALL_FAILED_INTERNAL_ERROR;
90 }
91 }
92
93 // check number of current installed third bundles whether is to MAX_THIRD_BUNDLE_NUMBER
94 if (bundleStyle == THIRD_APP_FLAG) {
95 uint32_t numOfBundles = GtManagerService::GetInstance().GetNumOfThirdBundles();
96 HILOG_INFO(HILOG_MODULE_AAFWK, "[BMS] bundle num is %d", numOfBundles);
97 if (GtManagerService::GetInstance().QueryBundleInfo(bundleName) == nullptr &&
98 numOfBundles >= MAX_THIRD_BUNDLE_NUMBER) {
99 HILOG_ERROR(HILOG_MODULE_AAFWK, "[BMS] bundle quantity exceeds the limit!");
100 UI_Free(bundleName);
101 return ERR_APPEXECFWK_INSTALL_FAILED_EXCEED_MAX_BUNDLE_NUMBER;
102 }
103 }
104 UI_Free(bundleName);
105 return ERR_OK;
106 }
107
VerifySignature(const char * path,SignatureInfo & signatureInfo,uint32_t & fileSize,uint8_t bundleStyle)108 uint8_t GtBundleInstaller::VerifySignature(const char *path, SignatureInfo &signatureInfo, uint32_t &fileSize,
109 uint8_t bundleStyle)
110 {
111 #ifdef _MINI_BMS_
112 VerifyResult verifyResult;
113 // verify signature
114 (void) APPVERI_SetDebugMode(true);
115 int32_t ret = APPVERI_AppVerify(path, &verifyResult);
116 HILOG_INFO(HILOG_MODULE_AAFWK, "[BMS] APPVERI_AppVerify is %d", ret);
117 uint8_t errorCode = SwitchErrorCode(ret);
118 if (errorCode != ERR_OK) {
119 return errorCode;
120 }
121 fileSize = APPVERI_GetUnsignedFileLength(path);
122 signatureInfo.appId = Utils::Strdup(verifyResult.profile.appid);
123 signatureInfo.bundleName = Utils::Strdup(verifyResult.profile.bundleInfo.bundleName);
124 if (signatureInfo.appId == nullptr || signatureInfo.bundleName == nullptr) {
125 APPVERI_FreeVerifyRst(&verifyResult);
126 FREE_SIGNATUREINFO(signatureInfo);
127 return ERR_APPEXECFWK_INSTALL_FAILED_INTERNAL_ERROR;
128 }
129 signatureInfo.restricNum = verifyResult.profile.permission.restricNum;
130 if (signatureInfo.restricNum == 0) {
131 APPVERI_FreeVerifyRst(&verifyResult);
132 return ERR_OK;
133 }
134 char **restricPermission = verifyResult.profile.permission.restricPermission;
135 signatureInfo.restricPermission = reinterpret_cast<char **>(AdapterMalloc(sizeof(char *) *
136 signatureInfo.restricNum));
137 if (signatureInfo.restricPermission == nullptr) {
138 APPVERI_FreeVerifyRst(&verifyResult);
139 FREE_SIGNATUREINFO(signatureInfo);
140 return ERR_APPEXECFWK_INSTALL_FAILED_INTERNAL_ERROR;
141 }
142 for (int i = 0; i < signatureInfo.restricNum; i++) {
143 *(signatureInfo.restricPermission + i) = Utils::Strdup(*(restricPermission + i));
144 if (*(signatureInfo.restricPermission + i) == nullptr) {
145 APPVERI_FreeVerifyRst(&verifyResult);
146 FREE_SIGNATUREINFO(signatureInfo);
147 return ERR_APPEXECFWK_INSTALL_FAILED_INTERNAL_ERROR;
148 }
149 }
150 APPVERI_FreeVerifyRst(&verifyResult);
151 #endif
152 return ERR_OK;
153 }
154
SwitchErrorCode(int32_t errorCode)155 uint8_t GtBundleInstaller::SwitchErrorCode(int32_t errorCode)
156 {
157 if (errorCode >= V_ERR_GET_CERT_INFO && errorCode <= V_ERR_GET_CERT_TYPE) {
158 return ERR_APPEXECFWK_INSTALL_FAILED_PARSE_APP_SIGNATURE_ERROR;
159 } else if (errorCode >= V_ERR_GET_PROFILE_DATA && errorCode <= V_ERR_INVALID_DEVID) {
160 return ERR_APPEXECFWK_INSTALL_FAILED_PARSE_PROFILE_SIGNATURE_ERROR;
161 } else if (errorCode >= V_ERR_FILE_OPEN && errorCode <= V_ERR_FILE_LENGTH) {
162 return ERR_APPEXECFWK_INSTALL_FAILED_OPERATE_SIGNED_FILE_ERROR;
163 } else if ((errorCode >= V_ERR_MEMSET && errorCode <= V_ERR_MALLOC) || errorCode == V_ERR) {
164 return ERR_APPEXECFWK_INSTALL_FAILED_INTERNAL_SIGNATURE_ERROR;
165 } else {
166 return ERR_OK;
167 }
168 }
169
Install(const char * path,InstallerCallback installerCallback)170 uint8_t GtBundleInstaller::Install(const char *path, InstallerCallback installerCallback)
171 {
172 if (path == nullptr) {
173 return ERR_APPEXECFWK_INSTALL_FAILED_PARAM_ERROR;
174 }
175
176 InstallRecord installRecord = {
177 .bundleName = nullptr,
178 .codePath = nullptr,
179 .appId = nullptr,
180 #ifdef BC_TRANS_ENABLE
181 .jsEngineVersion = nullptr,
182 .transformResult = -1,
183 #endif
184 .versionCode = -1
185 };
186 // process bundle install
187 uint8_t bundleStyle = 0;
188 if (BundleUtil::StartWith(path, SYSTEM_BUNDLE_PATH)) {
189 bundleStyle = SYSTEM_APP_FLAG;
190 } else if (BundleUtil::StartWith(path, THIRD_SYSTEM_BUNDLE_PATH)) {
191 bundleStyle = THIRD_SYSTEM_APP_FLAG;
192 } else {
193 bundleStyle = THIRD_APP_FLAG;
194 }
195 char randStr[RADN_NUM] = { 0 };
196 BundleUtil::CreateRandStr(randStr, RADN_NUM);
197 if (strlen(randStr) == 0) {
198 HILOG_ERROR(HILOG_MODULE_AAFWK, "[BMS] create random str fail!");
199 return ERR_APPEXECFWK_INSTALL_FAILED_INTERNAL_ERROR;
200 }
201
202 bool isUpdate = false;
203 uint8_t errorCode = ProcessBundleInstall(path, randStr, installRecord, bundleStyle, installerCallback, isUpdate);
204 if (errorCode != ERR_OK) {
205 return errorCode;
206 }
207 (void) GtManagerService::GetInstance().ReportInstallCallback(OPERATION_DOING, 0, BMS_SIXTH_FINISHED_PROCESS,
208 installerCallback);
209
210 // rename bundle.json
211 if (!RenameJsonFile(installRecord.bundleName, randStr)) {
212 BundleInfo *bundleInfo = GtManagerService::GetInstance().QueryBundleInfo(installRecord.bundleName);
213 CLEAR_INSTALL_ENV(bundleInfo);
214 return ERR_APPEXECFWK_INSTALL_FAILED_RENAME_FILE_ERROR;
215 }
216 // if third system bundle, it need to record bundleName in THIRD_SYSTEM_BUNDLE_JSON
217 if (bundleStyle == THIRD_SYSTEM_APP_FLAG && !CheckIsThirdSystemBundle(installRecord.bundleName)) {
218 RecordThirdSystemBundle(installRecord.bundleName, THIRD_SYSTEM_BUNDLE_JSON);
219 }
220
221 if (bundleStyle == THIRD_APP_FLAG && !isUpdate) {
222 GtManagerService::GetInstance().AddNumOfThirdBundles();
223 }
224 // record app info event when install app
225 return ERR_OK;
226 }
227
ProcessBundleInstall(const char * path,const char * randStr,InstallRecord & installRecord,uint8_t bundleStyle,InstallerCallback installerCallback,bool & isUpdate)228 uint8_t GtBundleInstaller::ProcessBundleInstall(const char *path, const char *randStr, InstallRecord &installRecord,
229 uint8_t bundleStyle, InstallerCallback installerCallback, bool &isUpdate)
230 {
231 SignatureInfo signatureInfo;
232 signatureInfo = {.bundleName = nullptr, .appId = nullptr, .restricPermission = nullptr, .restricNum = 0};
233 int32_t fp = -1;
234 uint32_t fileSize = 0;
235 // check bundle whether is valid
236 Permissions permissions = {.permNum = 0, .permissionTrans = nullptr};
237 BundleRes bundleRes = {
238 .bundleName = nullptr, .moduleDescriptionId = 0, .abilityRes = nullptr, .totalNumOfAbilityRes = 0
239 };
240 BundleInfo *bundleInfo = nullptr;
241 (void) GtManagerService::GetInstance().ReportInstallCallback(OPERATION_DOING, 0,
242 BMS_FIRST_FINISHED_PROCESS, installerCallback);
243 uint8_t errorCode = PreCheckBundle(path, fp, signatureInfo, fileSize, bundleStyle);
244 CHECK_PRO_RESULT(errorCode, fp, permissions, bundleInfo, signatureInfo);
245 (void) GtManagerService::GetInstance().ReportInstallCallback(OPERATION_DOING,
246 0, BMS_SECOND_FINISHED_PROCESS, installerCallback);
247 // parse HarmoyProfile.json, get permissions and bundleInfo
248 RefreshAllServiceTimeStamp();
249 errorCode = GtBundleParser::ParseHapProfile(fp, fileSize, permissions, bundleRes, &bundleInfo);
250 CHECK_PRO_RESULT(errorCode, fp, permissions, bundleInfo, signatureInfo);
251 SetCurrentBundle(bundleInfo->bundleName);
252 // terminate current runing app
253 uint32_t labelId = (bundleRes.abilityRes != nullptr) ? bundleRes.abilityRes->labelId : 0;
254 uint32_t iconId = (bundleRes.abilityRes != nullptr) ? bundleRes.abilityRes->iconId : 0;
255 AdapterFree(bundleRes.abilityRes);
256 // check signatureInfo
257 #ifdef _MINI_BMS_
258 errorCode = CheckProvisionInfoIsValid(signatureInfo, permissions, bundleInfo->bundleName);
259 CHECK_PRO_RESULT(errorCode, fp, permissions, bundleInfo, signatureInfo);
260 #endif
261 installRecord.codePath = bundleInfo->codePath;
262 installRecord.bundleName = bundleInfo->bundleName;
263 #ifdef _MINI_BMS_
264 installRecord.appId = signatureInfo.appId;
265 bundleInfo->appId = Utils::Strdup(signatureInfo.appId);
266 #else
267 char innerAppId[] = "appId";
268 installRecord.appId = innerAppId;
269 bundleInfo->appId = Utils::Strdup(innerAppId);
270 #endif
271 installRecord.versionCode = bundleInfo->versionCode;
272 // check version when in update status
273 errorCode = CheckVersionAndSignature(installRecord.bundleName, installRecord.appId, bundleInfo);
274 CHECK_PRO_RESULT(errorCode, fp, permissions, bundleInfo, signatureInfo);
275 // restore bin data to file
276 char *tmpCodePathComp[] = {installRecord.codePath, const_cast<char *>(randStr)};
277 char *tmpCodePath = BundleUtil::Strscat(tmpCodePathComp, sizeof(tmpCodePathComp) / sizeof(char *));
278 errorCode = (tmpCodePath == nullptr) ? ERR_APPEXECFWK_INSTALL_FAILED_INTERNAL_ERROR : ERR_OK;
279 CHECK_PRO_RESULT(errorCode, fp, permissions, bundleInfo, signatureInfo);
280 RefreshAllServiceTimeStamp();
281 errorCode = GtBundleExtractor::ExtractHap(tmpCodePath, installRecord.bundleName, fp, fileSize, bundleStyle);
282 close(fp);
283 CHECK_PRO_PART_ROLLBACK(errorCode, tmpCodePath, permissions, bundleInfo, signatureInfo);
284 (void) GtManagerService::GetInstance().ReportInstallCallback(OPERATION_DOING, 0,
285 BMS_THIRD_FINISHED_PROCESS, installerCallback);
286 // get js engine version
287 #ifdef BC_TRANS_ENABLE
288 char *jsEngineVersion = get_jerry_version_no();
289 errorCode = (jsEngineVersion != nullptr) ? ERR_OK : ERR_APPEXECFWK_INSTALL_FAILED_GET_JS_ENGINE_VERSION_ERROR;
290 CHECK_PRO_PART_ROLLBACK(errorCode, tmpCodePath, permissions, bundleInfo, signatureInfo);
291 installRecord.jsEngineVersion = jsEngineVersion;
292 // try to transform js file to bc file
293 RefreshAllServiceTimeStamp();
294 errorCode = TransformJsToBc(tmpCodePath, installRecord);
295 CHECK_PRO_PART_ROLLBACK(errorCode, tmpCodePath, permissions, bundleInfo, signatureInfo);
296 #endif
297 (void) GtManagerService::GetInstance().ReportInstallCallback(OPERATION_DOING, 0,
298 BMS_FOURTH_FINISHED_PROCESS, installerCallback);
299 // rename install path and record install infomation
300 isUpdate = GtManagerService::GetInstance().QueryBundleInfo(installRecord.bundleName) != nullptr;
301 errorCode = HandleFileAndBackUpRecord(installRecord, tmpCodePath, randStr, bundleInfo->dataPath, isUpdate);
302 AdapterFree(tmpCodePath);
303 CHECK_PRO_ROLLBACK(errorCode, permissions, bundleInfo, signatureInfo, randStr);
304 RefreshAllServiceTimeStamp();
305 // move rawfile to data path when rawfile is exists
306 errorCode = MoveRawFileToDataPath(bundleInfo);
307 CHECK_PRO_ROLLBACK(errorCode, permissions, bundleInfo, signatureInfo, randStr);
308 (void) GtManagerService::GetInstance().ReportInstallCallback(OPERATION_DOING, 0,
309 BMS_FIFTH_FINISHED_PROCESS, installerCallback);
310 // store permissions
311 errorCode = StorePermissions(installRecord.bundleName, permissions.permissionTrans, permissions.permNum,
312 isUpdate);
313 CHECK_PRO_ROLLBACK(errorCode, permissions, bundleInfo, signatureInfo, randStr);
314 // update bundle Info
315 errorCode = UpdateBundleInfo(bundleStyle, labelId, iconId, bundleInfo, isUpdate);
316 CHECK_PRO_ROLLBACK(errorCode, permissions, bundleInfo, signatureInfo, randStr);
317 // free memory
318 UI_Free(permissions.permissionTrans);
319 FREE_SIGNATUREINFO(signatureInfo);
320 return ERR_OK;
321 }
322
MoveRawFileToDataPath(const BundleInfo * bundleInfo)323 uint8_t GtBundleInstaller::MoveRawFileToDataPath(const BundleInfo *bundleInfo)
324 {
325 if (bundleInfo == nullptr) {
326 return ERR_APPEXECFWK_INSTALL_FAILED_INTERNAL_ERROR;
327 }
328
329 char *srcRawFilePathComp[] = {
330 const_cast<char *>(bundleInfo->codePath), const_cast<char *>(ASSETS),
331 const_cast<char *>(bundleInfo->moduleInfos[0].moduleName), const_cast<char *>(RESOURCES_RAW_FILE)
332 };
333 char *srcRawFilePath = BundleUtil::Strscat(srcRawFilePathComp, sizeof(srcRawFilePathComp) / sizeof(char *));
334 if (srcRawFilePath == nullptr) {
335 HILOG_ERROR(HILOG_MODULE_AAFWK, "[BMS] srcRawFilePath is nullptr");
336 return ERR_APPEXECFWK_INSTALL_FAILED_INTERNAL_ERROR;
337 }
338
339 if (!BundleUtil::IsDir(srcRawFilePath)) {
340 HILOG_INFO(HILOG_MODULE_AAFWK, "[BMS] rawfile is not exists!");
341 AdapterFree(srcRawFilePath);
342 return ERR_OK;
343 }
344
345 char *dstRawFilePathComp[] = {const_cast<char *>(bundleInfo->dataPath), const_cast<char *>(RAW_FILE)};
346 char *dstRawFilePath = BundleUtil::Strscat(dstRawFilePathComp, sizeof(dstRawFilePathComp) / sizeof(char *));
347 if (dstRawFilePath == nullptr) {
348 HILOG_ERROR(HILOG_MODULE_AAFWK, "[BMS] dstRawFilePath is nullptr");
349 AdapterFree(srcRawFilePath);
350 return ERR_APPEXECFWK_INSTALL_FAILED_INTERNAL_ERROR;
351 }
352
353 if (!BundleUtil::RenameDir(srcRawFilePath, dstRawFilePath)) {
354 HILOG_ERROR(HILOG_MODULE_AAFWK, "[BMS] frename rawfile fail!");
355 AdapterFree(srcRawFilePath);
356 AdapterFree(dstRawFilePath);
357 return ERR_APPEXECFWK_INSTALL_FAILED_RENAME_DIR_ERROR;
358 }
359 AdapterFree(srcRawFilePath);
360 AdapterFree(dstRawFilePath);
361 return ERR_OK;
362 }
363
ReshapeAppId(const char * bundleName,char * appId)364 char *GtBundleInstaller::ReshapeAppId(const char *bundleName, char *appId)
365 {
366 if (appId == nullptr || bundleName == nullptr) {
367 return nullptr;
368 }
369
370 char *pos = appId;
371 for (int32_t i = 0; appId[i] != '\0'; i++) {
372 if (appId[i] == '_') {
373 break;
374 }
375 pos++;
376 }
377
378 char *appIdComp[] = {const_cast<char *>(bundleName), pos};
379 char *newAppid = BundleUtil::Strscat(appIdComp, sizeof(appIdComp) / sizeof(char *));
380 AdapterFree(appId);
381 return newAppid;
382 }
383
CheckProvisionInfoIsValid(const SignatureInfo & signatureInfo,const Permissions & permissions,const char * bundleName)384 uint8_t GtBundleInstaller::CheckProvisionInfoIsValid(const SignatureInfo &signatureInfo, const Permissions &permissions,
385 const char *bundleName)
386 {
387 if (bundleName == nullptr) {
388 return ERR_APPEXECFWK_INSTALL_FAILED_INTERNAL_ERROR;
389 }
390
391 if (!MatchBundleName(bundleName, signatureInfo.bundleName)) {
392 return ERR_APPEXECFWK_INSTALL_FAILED_INVALID_PROVISIONINFO;
393 }
394 return ERR_OK;
395 }
396
397
MatchBundleName(const char * bundleName,const char * matchedBundleName)398 bool GtBundleInstaller::MatchBundleName(const char *bundleName, const char *matchedBundleName)
399 {
400 if (bundleName == nullptr || matchedBundleName == nullptr) {
401 return false;
402 }
403
404 if (strcmp(matchedBundleName, MATCHED_ALL_STR) == 0 || strcmp(bundleName, matchedBundleName) == 0) {
405 return true;
406 }
407
408 char *pos = const_cast<char *>(matchedBundleName);
409 for (uint32_t i = 0; matchedBundleName[i] != '\0' && bundleName[i] != '\0'; i++, pos++) {
410 if (bundleName[i] != matchedBundleName[i]) {
411 if (strcmp(pos, MATCHED_ALL_STR) == 0) {
412 return true;
413 }
414 return false;
415 } else if (strcmp(pos, MATCHED_ALL_STR) == 0) {
416 return true;
417 }
418 }
419 return false;
420 }
421
MatchPermissions(char ** restrictedPermissions,uint32_t restricNum,PermissionTrans * permissionsTrans,int32_t permTransNum)422 bool GtBundleInstaller::MatchPermissions(char ** restrictedPermissions, uint32_t restricNum,
423 PermissionTrans *permissionsTrans, int32_t permTransNum)
424 {
425 if (permTransNum == 0) {
426 return true;
427 }
428
429 if (permissionsTrans == nullptr || restrictedPermissions == nullptr) {
430 return false;
431 }
432
433 PermissionTrans *perm = permissionsTrans;
434 for (int32_t i = 0; i < permTransNum; i++) {
435 bool isMatched = false;
436 for (int32_t j = 0; j < restricNum; j++) {
437 if (((perm + i)->name != nullptr) && strcmp(*(restrictedPermissions + j), (perm + i)->name) == 0) {
438 isMatched = true;
439 break;
440 }
441 }
442 if (!isMatched) {
443 return false;
444 }
445 }
446 return true;
447 }
448
HandleFileAndBackUpRecord(const InstallRecord & record,const char * tmpPath,const char * randStr,const char * dataPath,bool isUpdate)449 uint8_t GtBundleInstaller::HandleFileAndBackUpRecord(const InstallRecord &record, const char *tmpPath,
450 const char *randStr, const char *dataPath, bool isUpdate)
451 {
452 if (tmpPath == nullptr || dataPath == nullptr) {
453 return ERR_APPEXECFWK_INSTALL_FAILED_INTERNAL_ERROR;
454 }
455 // delete old bundleRes
456 GtManagerService::GetInstance().RemoveBundleResList(record.bundleName);
457
458 if (!BundleUtil::RenameDir(tmpPath, record.codePath)) {
459 BundleUtil::RemoveDir(tmpPath);
460 return ERR_APPEXECFWK_INSTALL_FAILED_RENAME_DIR_ERROR;
461 }
462
463 char *bundleTmpJsonPathComp[] = {
464 const_cast<char *>(JSON_PATH), const_cast<char *>(record.bundleName), const_cast<char *>(randStr),
465 const_cast<char *>(JSON_SUFFIX)
466 };
467 char *bundleTmpJsonPath = BundleUtil::Strscat(bundleTmpJsonPathComp,
468 sizeof(bundleTmpJsonPathComp) / sizeof(char *));
469 if (bundleTmpJsonPath == nullptr) {
470 return ERR_APPEXECFWK_INSTALL_FAILED_RECORD_INFO_ERROR;
471 }
472
473 if (!BackUpInstallRecord(record, bundleTmpJsonPath)) {
474 unlink(bundleTmpJsonPath);
475 AdapterFree(bundleTmpJsonPath);
476 return ERR_APPEXECFWK_INSTALL_FAILED_RECORD_INFO_ERROR;
477 }
478 AdapterFree(bundleTmpJsonPath);
479
480 if (!isUpdate) {
481 (void) BundleUtil::RemoveDir(dataPath);
482 if (!BundleUtil::MkDirs(dataPath)) {
483 return ERR_APPEXECFWK_INSTALL_FAILED_CREATE_DATA_DIR_ERROR;
484 }
485 }
486 return ERR_OK;
487 }
488
489 #ifdef BC_TRANS_ENABLE
TransformJsToBc(const char * codePath,InstallRecord & record)490 uint8_t GtBundleInstaller::TransformJsToBc(const char *codePath, InstallRecord &record)
491 {
492 if (codePath == nullptr) {
493 return ERR_APPEXECFWK_INSTALL_FAILED_INTERNAL_ERROR;
494 }
495
496 char *jsPathComp[] = {const_cast<char *>(codePath), const_cast<char *>(ASSET_JS_PATH)};
497 char *jsPath = BundleUtil::Strscat(jsPathComp, sizeof(jsPathComp) / sizeof(char *));
498 if (jsPath == nullptr) {
499 return ERR_APPEXECFWK_INSTALL_FAILED_INTERNAL_ERROR;
500 }
501 if (!BundleUtil::IsDir(jsPath)) {
502 AdapterFree(jsPath);
503 char *newJsPathComp[] = {const_cast<char *>(codePath), const_cast<char *>(NEW_ASSET_JS_PATH)};
504 jsPath = BundleUtil::Strscat(newJsPathComp, sizeof(newJsPathComp) / sizeof(char *));
505 if (jsPath == nullptr) {
506 return ERR_APPEXECFWK_INSTALL_FAILED_INTERNAL_ERROR;
507 }
508 }
509 EXECRES result = walk_directory(jsPath);
510 HILOG_INFO(HILOG_MODULE_AAFWK, "[BMS] transform js to bc when install, result is %d", result);
511 if (result != EXCE_ACE_JERRY_EXEC_OK) {
512 AdapterFree(jsPath);
513 return ERR_APPEXECFWK_INSTALL_FAILED_TRANSFORM_BC_FILE_ERROR;
514 }
515 AdapterFree(jsPath);
516 record.transformResult = 0;
517 return ERR_OK;
518 }
519 #endif
520
UpdateBundleInfo(uint8_t bundleStyle,uint32_t labelId,uint32_t iconId,BundleInfo * bundleInfo,bool isUpdate)521 uint8_t GtBundleInstaller::UpdateBundleInfo(uint8_t bundleStyle, uint32_t labelId, uint32_t iconId,
522 BundleInfo *bundleInfo, bool isUpdate)
523 {
524 if (bundleInfo == nullptr || bundleInfo->abilityInfo == nullptr) {
525 return ERR_APPEXECFWK_INSTALL_FAILED_INTERNAL_ERROR;
526 }
527
528 if (!BundleUtil::IsDir(bundleInfo->abilityInfo->srcPath)) {
529 return ERR_APPEXECFWK_INSTALL_FAILED_PARSE_JS_DIR_ERROR;
530 }
531
532 uint8_t errorCode = GtBundleParser::ConvertResInfoToBundleInfo(bundleInfo->codePath, labelId, iconId, bundleInfo);
533 if (errorCode != ERR_OK) {
534 return errorCode;
535 }
536 if (!isUpdate) {
537 if (bundleStyle == SYSTEM_APP_FLAG) {
538 bundleInfo->isSystemApp = true;
539 GtManagerService::GetInstance().AddBundleInfo(bundleInfo);
540 } else {
541 bundleInfo->isSystemApp = false;
542 GtManagerService::GetInstance().AddBundleInfo(bundleInfo);
543 }
544 } else {
545 BundleInfo *oldBundleInfo = GtManagerService::GetInstance().QueryBundleInfo(bundleInfo->bundleName);
546 if (oldBundleInfo == nullptr) {
547 return ERR_APPEXECFWK_INSTALL_FAILED_INTERNAL_ERROR;
548 }
549 bundleInfo->isSystemApp = oldBundleInfo->isSystemApp;
550
551 if (!GtManagerService::GetInstance().UpdateBundleInfo(bundleInfo)) {
552 return ERR_APPEXECFWK_INSTALL_FAILED_INTERNAL_ERROR;
553 }
554 }
555 // update bundle res list
556 return AddBundleResList(bundleInfo->bundleName, labelId, iconId);
557 }
558
AddBundleResList(const char * bundleName,uint32_t labelId,uint32_t iconId)559 uint8_t GtBundleInstaller::AddBundleResList(const char *bundleName, uint32_t labelId, uint32_t iconId)
560 {
561 if (labelId == 0 && iconId == 0) {
562 return ERR_OK;
563 }
564
565 if (bundleName == nullptr) {
566 return ERR_APPEXECFWK_INSTALL_FAILED_INTERNAL_ERROR;
567 }
568
569 BundleRes *bundleRes = reinterpret_cast<BundleRes *>(AdapterMalloc(sizeof(BundleRes)));
570 if (bundleRes == nullptr) {
571 return ERR_APPEXECFWK_INSTALL_FAILED_INTERNAL_ERROR;
572 }
573
574 bundleRes->abilityRes = reinterpret_cast<AbilityRes *>(AdapterMalloc(sizeof(AbilityRes)));
575 if (bundleRes->abilityRes == nullptr) {
576 AdapterFree(bundleRes);
577 return ERR_APPEXECFWK_INSTALL_FAILED_INTERNAL_ERROR;
578 }
579 bundleRes->bundleName = const_cast<char *>(bundleName);
580 bundleRes->abilityRes->labelId = labelId;
581 bundleRes->abilityRes->iconId = iconId;
582
583 GtManagerService::GetInstance().AddBundleResList(bundleRes);
584 return ERR_OK;
585 }
586
Uninstall(const char * bundleName)587 uint8_t GtBundleInstaller::Uninstall(const char *bundleName)
588 {
589 if (bundleName == nullptr) {
590 return ERR_APPEXECFWK_UNINSTALL_FAILED_PARAM_ERROR;
591 }
592
593 BundleInfo *bundleInfo = GtManagerService::GetInstance().QueryBundleInfo(bundleName);
594 if (bundleInfo == nullptr) {
595 return ERR_APPEXECFWK_UNINSTALL_FAILED_BUNDLE_NOT_EXISTS;
596 }
597
598 if (bundleInfo->isSystemApp) {
599 return ERR_APPEXECFWK_UNINSTALL_FAILED_BUNDLE_NOT_UNINSTALLABLE;
600 }
601
602 char bundleJsonPath[PATH_LENGTH] = { 0 };
603 if (sprintf_s(bundleJsonPath, PATH_LENGTH, "%s%s%s", JSON_PATH, bundleName, JSON_SUFFIX) < 0) {
604 return ERR_APPEXECFWK_UNINSTALL_FAILED_INTERNAL_ERROR;
605 }
606 #ifdef _MINI_BMS_PERMISSION_
607 if (DeletePermissions(const_cast<char *>(bundleName)) < 0) {
608 return ERR_APPEXECFWK_UNINSTALL_FAILED_DELETE_PERMISSIONS_ERROR;
609 }
610 #endif
611 bool res = CheckIsThirdSystemBundle(bundleName);
612 if (!(BundleUtil::RemoveDir(bundleInfo->codePath) && BundleUtil::RemoveDir(bundleInfo->dataPath))) {
613 GtManagerService::GetInstance().RemoveBundleInfo(bundleName);
614 GtManagerService::GetInstance().RemoveBundleResList(bundleName);
615 if (!res) {
616 GtManagerService::GetInstance().ReduceNumOfThirdBundles();
617 }
618 return ERR_APPEXECFWK_UNINSTALL_FAILED_DELETE_DIRS_ERROR;
619 }
620
621 GtManagerService::GetInstance().RemoveBundleInfo(bundleName);
622 GtManagerService::GetInstance().RemoveBundleResList(bundleName);
623 if (!res) {
624 GtManagerService::GetInstance().ReduceNumOfThirdBundles();
625 }
626 if (unlink(bundleJsonPath) < 0) {
627 return ERR_APPEXECFWK_UNINSTALL_FAILED_DELETE_RECORD_INFO_ERROR;
628 }
629
630 if (res) {
631 RecordThirdSystemBundle(bundleName, UNINSTALL_THIRD_SYSTEM_BUNDLE_JSON);
632 }
633
634 return ERR_OK;
635 }
636
CheckIsThirdSystemBundle(const char * bundleName)637 bool GtBundleInstaller::CheckIsThirdSystemBundle(const char *bundleName)
638 {
639 if (bundleName == nullptr) {
640 return false;
641 }
642 cJSON *root = BundleUtil::GetJsonStream(THIRD_SYSTEM_BUNDLE_JSON);
643 if (root == nullptr) {
644 return false;
645 }
646
647 cJSON *son = cJSON_GetObjectItem(root, JSON_MAIN_KEY);
648 if (!cJSON_IsArray(son)) {
649 (void) unlink(THIRD_SYSTEM_BUNDLE_JSON);
650 cJSON_Delete(root);
651 return false;
652 }
653
654 cJSON *item = nullptr;
655 cJSON_ArrayForEach(item, son) {
656 if (!cJSON_IsString(item)) {
657 cJSON_Delete(root);
658 return false;
659 }
660 if ((item->valuestring != nullptr) && strcmp(bundleName, item->valuestring) == 0) {
661 cJSON_Delete(root);
662 return true;
663 }
664 }
665 cJSON_Delete(root);
666 return false;
667 }
668
RecordThirdSystemBundle(const char * bundleName,const char * path)669 void GtBundleInstaller::RecordThirdSystemBundle(const char *bundleName, const char *path)
670 {
671 if (bundleName == nullptr || path == nullptr) {
672 return;
673 }
674 if (BundleUtil::IsFile(path)) {
675 cJSON *root = BundleUtil::GetJsonStream(path);
676 if (root == nullptr) {
677 return;
678 }
679
680 cJSON *son = cJSON_GetObjectItem(root, JSON_MAIN_KEY);
681 if (!cJSON_IsArray(son)) {
682 unlink(path);
683 cJSON_Delete(root);
684 InitThirdSystemBundleRecord(bundleName, path);
685 return;
686 }
687
688 cJSON *str = cJSON_CreateString(bundleName);
689 if (str == nullptr) {
690 cJSON_Delete(root);
691 return;
692 }
693 cJSON_AddItemToArray(son, str);
694
695 (void) BundleUtil::StoreJsonContentToFile(path, root);
696 cJSON_Delete(root);
697 } else {
698 InitThirdSystemBundleRecord(bundleName, path);
699 }
700 }
701
InitThirdSystemBundleRecord(const char * bundleName,const char * path)702 void GtBundleInstaller::InitThirdSystemBundleRecord(const char *bundleName, const char *path)
703 {
704 if (bundleName == nullptr || path == nullptr) {
705 return;
706 }
707 cJSON *root = cJSON_CreateObject();
708 if (root == nullptr) {
709 return;
710 }
711
712 cJSON *son = cJSON_CreateArray();
713 if (son == nullptr) {
714 cJSON_Delete(root);
715 return;
716 }
717
718 if (!cJSON_AddItemToObject(root, JSON_MAIN_KEY, son)) {
719 cJSON_Delete(son);
720 cJSON_Delete(root);
721 return;
722 }
723
724 cJSON *str = cJSON_CreateString(bundleName);
725 if (str == nullptr) {
726 cJSON_Delete(root);
727 return;
728 }
729
730 if (!cJSON_AddItemToArray(son, str)) {
731 cJSON_Delete(str);
732 cJSON_Delete(root);
733 return;
734 }
735
736 BundleUtil::StoreJsonContentToFile(path, root);
737 cJSON_Delete(root);
738 }
739
BackUpInstallRecord(const InstallRecord & record,const char * jsonPath)740 bool GtBundleInstaller::BackUpInstallRecord(const InstallRecord &record, const char *jsonPath)
741 {
742 if (jsonPath == nullptr) {
743 return false;
744 }
745
746 cJSON *object = BundleUtil::ConvertInstallRecordToJson(record);
747 if (object == nullptr) {
748 return false;
749 }
750
751 if (!BundleUtil::StoreJsonContentToFile(jsonPath, object)) {
752 cJSON_Delete(object);
753 return false;
754 }
755 cJSON_Delete(object);
756 return true;
757 }
758
StorePermissions(const char * bundleName,PermissionTrans * permissions,int32_t permNum,bool isUpdate)759 uint8_t GtBundleInstaller::StorePermissions(const char *bundleName, PermissionTrans *permissions, int32_t permNum,
760 bool isUpdate)
761 {
762 if (permNum == 0) {
763 #ifdef _MINI_BMS_PERMISSION_
764 if (isUpdate) {
765 int32_t ret = DeletePermissions(bundleName);
766 HILOG_INFO(HILOG_MODULE_AAFWK, "[BMS] delete permissions, result is %d", ret);
767 }
768 #endif
769 return ERR_OK;
770 }
771
772 if (bundleName == nullptr || permissions == nullptr) {
773 return ERR_APPEXECFWK_INSTALL_FAILED_INTERNAL_ERROR;
774 }
775
776 if (!BundleUtil::IsDir(PERMISSIONS_PATH)) {
777 BundleUtil::MkDirs(PERMISSIONS_PATH);
778 }
779 #ifdef _MINI_BMS_PERMISSION_
780 if (SaveOrUpdatePermissions(const_cast<char *>(bundleName), permissions, permNum,
781 static_cast<IsUpdate>(isUpdate)) != 0) {
782 return ERR_APPEXECFWK_INSTALL_FAILED_STORE_PERMISSIONS_ERROR;
783 }
784 #endif
785 return ERR_OK;
786 }
787
CheckVersionAndSignature(const char * bundleName,const char * appId,BundleInfo * bundleInfo)788 uint8_t GtBundleInstaller::CheckVersionAndSignature(const char *bundleName, const char *appId, BundleInfo *bundleInfo)
789 {
790 if (bundleName == nullptr || appId == nullptr || bundleInfo == nullptr) {
791 return ERR_APPEXECFWK_INSTALL_FAILED_INTERNAL_ERROR;
792 }
793 BundleInfo *oldBundleInfo = GtManagerService::GetInstance().QueryBundleInfo(bundleName);
794 if (oldBundleInfo != nullptr) {
795 if (oldBundleInfo->versionCode > bundleInfo->versionCode) {
796 return ERR_APPEXECFWK_INSTALL_FAILED_VERSION_DOWNGRADE;
797 }
798 char *oldAppId = BundleUtil::GetValueFromBundleJson(bundleName, JSON_SUB_KEY_APPID);
799 if (oldAppId == nullptr) {
800 return ERR_APPEXECFWK_INSTALL_FAILED_INTERNAL_ERROR;
801 }
802 if (strcmp(oldAppId, appId) != 0) {
803 AdapterFree(oldAppId);
804 return ERR_APPEXECFWK_INSTALL_FAILED_INCOMPATIBLE_SIGNATURE;
805 }
806 AdapterFree(oldAppId);
807 }
808 return ERR_OK;
809 }
810
RenameJsonFile(const char * fileName,const char * randStr)811 bool GtBundleInstaller::RenameJsonFile(const char *fileName, const char *randStr)
812 {
813 if (fileName == nullptr || randStr == nullptr) {
814 return false;
815 }
816
817 char *tmpJsonPathComp[] = {
818 const_cast<char *>(JSON_PATH), const_cast<char *>(fileName), const_cast<char *>(randStr),
819 const_cast<char *>(JSON_SUFFIX)
820 };
821 char *tmpJsonPath = BundleUtil::Strscat(tmpJsonPathComp, sizeof(tmpJsonPathComp) / sizeof(char *));
822 if (tmpJsonPath == nullptr) {
823 return false;
824 }
825
826 if (!BundleUtil::IsFile(tmpJsonPath)) {
827 AdapterFree(tmpJsonPath);
828 return false;
829 }
830
831 char *jsonPathComp[] = {
832 const_cast<char *>(JSON_PATH), const_cast<char *>(fileName), const_cast<char *>(JSON_SUFFIX)
833 };
834 char *jsonPath = BundleUtil::Strscat(jsonPathComp, sizeof(jsonPathComp) / sizeof(char *));
835 if (jsonPath == nullptr) {
836 AdapterFree(tmpJsonPath);
837 return false;
838 }
839
840 if (!BundleUtil::RenameFile(tmpJsonPath, jsonPath)) {
841 AdapterFree(jsonPath);
842 AdapterFree(tmpJsonPath);
843 return false;
844 }
845
846 AdapterFree(jsonPath);
847 AdapterFree(tmpJsonPath);
848 return true;
849 }
850 } // namespace OHOS