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