• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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     EXECRES result = walk_directory(jsPath);
502     HILOG_INFO(HILOG_MODULE_AAFWK, "[BMS] transform js to bc when install, result is %d", result);
503     if (result != EXCE_ACE_JERRY_EXEC_OK) {
504         AdapterFree(jsPath);
505         return ERR_APPEXECFWK_INSTALL_FAILED_TRANSFORM_BC_FILE_ERROR;
506     }
507     AdapterFree(jsPath);
508     record.transformResult = 0;
509     return ERR_OK;
510 }
511 #endif
512 
UpdateBundleInfo(uint8_t bundleStyle,uint32_t labelId,uint32_t iconId,BundleInfo * bundleInfo,bool isUpdate)513 uint8_t GtBundleInstaller::UpdateBundleInfo(uint8_t bundleStyle, uint32_t labelId, uint32_t iconId,
514     BundleInfo *bundleInfo, bool isUpdate)
515 {
516     if (bundleInfo == nullptr || bundleInfo->abilityInfo == nullptr) {
517         return ERR_APPEXECFWK_INSTALL_FAILED_INTERNAL_ERROR;
518     }
519 
520     if (!BundleUtil::IsDir(bundleInfo->abilityInfo->srcPath)) {
521         return ERR_APPEXECFWK_INSTALL_FAILED_PARSE_JS_DIR_ERROR;
522     }
523 
524     uint8_t errorCode = GtBundleParser::ConvertResInfoToBundleInfo(bundleInfo->codePath, labelId, iconId, bundleInfo);
525     if (errorCode != ERR_OK) {
526         return errorCode;
527     }
528     if (!isUpdate) {
529         if (bundleStyle == SYSTEM_APP_FLAG) {
530             bundleInfo->isSystemApp = true;
531             GtManagerService::GetInstance().AddBundleInfo(bundleInfo);
532         } else {
533             bundleInfo->isSystemApp = false;
534             GtManagerService::GetInstance().AddBundleInfo(bundleInfo);
535         }
536     } else {
537         BundleInfo *oldBundleInfo = GtManagerService::GetInstance().QueryBundleInfo(bundleInfo->bundleName);
538         if (oldBundleInfo == nullptr) {
539             return ERR_APPEXECFWK_INSTALL_FAILED_INTERNAL_ERROR;
540         }
541         bundleInfo->isSystemApp = oldBundleInfo->isSystemApp;
542 
543         if (!GtManagerService::GetInstance().UpdateBundleInfo(bundleInfo)) {
544             return ERR_APPEXECFWK_INSTALL_FAILED_INTERNAL_ERROR;
545         }
546     }
547     // update bundle res list
548     return AddBundleResList(bundleInfo->bundleName, labelId, iconId);
549 }
550 
AddBundleResList(const char * bundleName,uint32_t labelId,uint32_t iconId)551 uint8_t GtBundleInstaller::AddBundleResList(const char *bundleName, uint32_t labelId, uint32_t iconId)
552 {
553     if (labelId == 0 && iconId == 0) {
554         return ERR_OK;
555     }
556 
557     if (bundleName == nullptr) {
558         return ERR_APPEXECFWK_INSTALL_FAILED_INTERNAL_ERROR;
559     }
560 
561     BundleRes *bundleRes = reinterpret_cast<BundleRes *>(AdapterMalloc(sizeof(BundleRes)));
562     if (bundleRes == nullptr) {
563         return ERR_APPEXECFWK_INSTALL_FAILED_INTERNAL_ERROR;
564     }
565 
566     bundleRes->abilityRes = reinterpret_cast<AbilityRes *>(AdapterMalloc(sizeof(AbilityRes)));
567     if (bundleRes->abilityRes == nullptr) {
568         AdapterFree(bundleRes);
569         return ERR_APPEXECFWK_INSTALL_FAILED_INTERNAL_ERROR;
570     }
571     bundleRes->bundleName = const_cast<char *>(bundleName);
572     bundleRes->abilityRes->labelId = labelId;
573     bundleRes->abilityRes->iconId = iconId;
574 
575     GtManagerService::GetInstance().AddBundleResList(bundleRes);
576     return ERR_OK;
577 }
578 
Uninstall(const char * bundleName)579 uint8_t GtBundleInstaller::Uninstall(const char *bundleName)
580 {
581     if (bundleName == nullptr) {
582         return ERR_APPEXECFWK_UNINSTALL_FAILED_PARAM_ERROR;
583     }
584 
585     BundleInfo *bundleInfo = GtManagerService::GetInstance().QueryBundleInfo(bundleName);
586     if (bundleInfo == nullptr) {
587         return ERR_APPEXECFWK_UNINSTALL_FAILED_BUNDLE_NOT_EXISTS;
588     }
589 
590     if (bundleInfo->isSystemApp) {
591         return ERR_APPEXECFWK_UNINSTALL_FAILED_BUNDLE_NOT_UNINSTALLABLE;
592     }
593 
594     char bundleJsonPath[PATH_LENGTH] = { 0 };
595     if (sprintf_s(bundleJsonPath, PATH_LENGTH, "%s%s%s", JSON_PATH, bundleName, JSON_SUFFIX) < 0) {
596         return ERR_APPEXECFWK_UNINSTALL_FAILED_INTERNAL_ERROR;
597     }
598 #ifdef _MINI_BMS_PERMISSION_
599     if (DeletePermissions(const_cast<char *>(bundleName)) < 0) {
600         return ERR_APPEXECFWK_UNINSTALL_FAILED_DELETE_PERMISSIONS_ERROR;
601     }
602 #endif
603     bool res = CheckIsThirdSystemBundle(bundleName);
604     if (!(BundleUtil::RemoveDir(bundleInfo->codePath) && BundleUtil::RemoveDir(bundleInfo->dataPath))) {
605         GtManagerService::GetInstance().RemoveBundleInfo(bundleName);
606         GtManagerService::GetInstance().RemoveBundleResList(bundleName);
607         if (!res) {
608             GtManagerService::GetInstance().ReduceNumOfThirdBundles();
609         }
610         return ERR_APPEXECFWK_UNINSTALL_FAILED_DELETE_DIRS_ERROR;
611     }
612 
613     GtManagerService::GetInstance().RemoveBundleInfo(bundleName);
614     GtManagerService::GetInstance().RemoveBundleResList(bundleName);
615     if (!res) {
616         GtManagerService::GetInstance().ReduceNumOfThirdBundles();
617     }
618     if (unlink(bundleJsonPath) < 0) {
619         return ERR_APPEXECFWK_UNINSTALL_FAILED_DELETE_RECORD_INFO_ERROR;
620     }
621 
622     if (res) {
623         RecordThirdSystemBundle(bundleName, UNINSTALL_THIRD_SYSTEM_BUNDLE_JSON);
624     }
625 
626     return ERR_OK;
627 }
628 
CheckIsThirdSystemBundle(const char * bundleName)629 bool GtBundleInstaller::CheckIsThirdSystemBundle(const char *bundleName)
630 {
631     if (bundleName == nullptr) {
632         return false;
633     }
634     cJSON *root = BundleUtil::GetJsonStream(THIRD_SYSTEM_BUNDLE_JSON);
635     if (root == nullptr) {
636         return false;
637     }
638 
639     cJSON *son = cJSON_GetObjectItem(root, JSON_MAIN_KEY);
640     if (!cJSON_IsArray(son)) {
641         (void) unlink(THIRD_SYSTEM_BUNDLE_JSON);
642         cJSON_Delete(root);
643         return false;
644     }
645 
646     cJSON *item = nullptr;
647     cJSON_ArrayForEach(item, son) {
648         if (!cJSON_IsString(item)) {
649             cJSON_Delete(root);
650             return false;
651         }
652         if ((item->valuestring != nullptr) && strcmp(bundleName, item->valuestring) == 0) {
653             cJSON_Delete(root);
654             return true;
655         }
656     }
657     cJSON_Delete(root);
658     return false;
659 }
660 
RecordThirdSystemBundle(const char * bundleName,const char * path)661 void GtBundleInstaller::RecordThirdSystemBundle(const char *bundleName, const char *path)
662 {
663     if (bundleName == nullptr || path == nullptr) {
664         return;
665     }
666     if (BundleUtil::IsFile(path)) {
667         cJSON *root = BundleUtil::GetJsonStream(path);
668         if (root == nullptr) {
669             return;
670         }
671 
672         cJSON *son = cJSON_GetObjectItem(root, JSON_MAIN_KEY);
673         if (!cJSON_IsArray(son)) {
674             unlink(path);
675             cJSON_Delete(root);
676             InitThirdSystemBundleRecord(bundleName, path);
677             return;
678         }
679 
680         cJSON *str = cJSON_CreateString(bundleName);
681         if (str == nullptr) {
682             cJSON_Delete(root);
683             return;
684         }
685         cJSON_AddItemToArray(son, str);
686 
687         (void) BundleUtil::StoreJsonContentToFile(path, root);
688         cJSON_Delete(root);
689     } else {
690         InitThirdSystemBundleRecord(bundleName, path);
691     }
692 }
693 
InitThirdSystemBundleRecord(const char * bundleName,const char * path)694 void GtBundleInstaller::InitThirdSystemBundleRecord(const char *bundleName, const char *path)
695 {
696     if (bundleName == nullptr || path == nullptr) {
697         return;
698     }
699     cJSON *root = cJSON_CreateObject();
700     if (root == nullptr) {
701         return;
702     }
703 
704     cJSON *son = cJSON_CreateArray();
705     if (son == nullptr) {
706         cJSON_Delete(root);
707         return;
708     }
709 
710     if (!cJSON_AddItemToObject(root, JSON_MAIN_KEY, son)) {
711         cJSON_Delete(son);
712         cJSON_Delete(root);
713         return;
714     }
715 
716     cJSON *str = cJSON_CreateString(bundleName);
717     if (str == nullptr) {
718         cJSON_Delete(root);
719         return;
720     }
721 
722     if (!cJSON_AddItemToArray(son, str)) {
723         cJSON_Delete(str);
724         cJSON_Delete(root);
725         return;
726     }
727 
728     BundleUtil::StoreJsonContentToFile(path, root);
729     cJSON_Delete(root);
730 }
731 
BackUpInstallRecord(const InstallRecord & record,const char * jsonPath)732 bool GtBundleInstaller::BackUpInstallRecord(const InstallRecord &record, const char *jsonPath)
733 {
734     if (jsonPath == nullptr) {
735         return false;
736     }
737 
738     cJSON *object = BundleUtil::ConvertInstallRecordToJson(record);
739     if (object == nullptr) {
740         return false;
741     }
742 
743     if (!BundleUtil::StoreJsonContentToFile(jsonPath, object)) {
744         cJSON_Delete(object);
745         return false;
746     }
747     cJSON_Delete(object);
748     return true;
749 }
750 
StorePermissions(const char * bundleName,PermissionTrans * permissions,int32_t permNum,bool isUpdate)751 uint8_t GtBundleInstaller::StorePermissions(const char *bundleName, PermissionTrans *permissions, int32_t permNum,
752     bool isUpdate)
753 {
754     if (permNum == 0) {
755 #ifdef _MINI_BMS_PERMISSION_
756         if (isUpdate) {
757             int32_t ret = DeletePermissions(bundleName);
758             HILOG_INFO(HILOG_MODULE_AAFWK, "[BMS] delete permissions, result is %d", ret);
759         }
760 #endif
761         return ERR_OK;
762     }
763 
764     if (bundleName == nullptr || permissions == nullptr) {
765         return ERR_APPEXECFWK_INSTALL_FAILED_INTERNAL_ERROR;
766     }
767 
768     if (!BundleUtil::IsDir(PERMISSIONS_PATH)) {
769         BundleUtil::MkDirs(PERMISSIONS_PATH);
770     }
771 #ifdef _MINI_BMS_PERMISSION_
772     if (SaveOrUpdatePermissions(const_cast<char *>(bundleName), permissions, permNum,
773         static_cast<IsUpdate>(isUpdate)) != 0) {
774             return ERR_APPEXECFWK_INSTALL_FAILED_STORE_PERMISSIONS_ERROR;
775     }
776 #endif
777     return ERR_OK;
778 }
779 
CheckVersionAndSignature(const char * bundleName,const char * appId,BundleInfo * bundleInfo)780 uint8_t GtBundleInstaller::CheckVersionAndSignature(const char *bundleName, const char *appId, BundleInfo *bundleInfo)
781 {
782     if (bundleName == nullptr || appId == nullptr || bundleInfo == nullptr) {
783         return ERR_APPEXECFWK_INSTALL_FAILED_INTERNAL_ERROR;
784     }
785     BundleInfo *oldBundleInfo = GtManagerService::GetInstance().QueryBundleInfo(bundleName);
786     if (oldBundleInfo != nullptr) {
787         if (oldBundleInfo->versionCode > bundleInfo->versionCode) {
788             return ERR_APPEXECFWK_INSTALL_FAILED_VERSION_DOWNGRADE;
789         }
790         char *oldAppId = BundleUtil::GetValueFromBundleJson(bundleName, JSON_SUB_KEY_APPID);
791         if (oldAppId == nullptr) {
792             return ERR_APPEXECFWK_INSTALL_FAILED_INTERNAL_ERROR;
793         }
794         if (strcmp(oldAppId, appId) != 0) {
795             AdapterFree(oldAppId);
796             return ERR_APPEXECFWK_INSTALL_FAILED_INCOMPATIBLE_SIGNATURE;
797         }
798         AdapterFree(oldAppId);
799     }
800     return ERR_OK;
801 }
802 
RenameJsonFile(const char * fileName,const char * randStr)803 bool GtBundleInstaller::RenameJsonFile(const char *fileName, const char *randStr)
804 {
805     if (fileName == nullptr || randStr == nullptr) {
806         return false;
807     }
808 
809     char *tmpJsonPathComp[] = {
810         const_cast<char *>(JSON_PATH), const_cast<char *>(fileName), const_cast<char *>(randStr),
811         const_cast<char *>(JSON_SUFFIX)
812     };
813     char *tmpJsonPath = BundleUtil::Strscat(tmpJsonPathComp, sizeof(tmpJsonPathComp) / sizeof(char *));
814     if (tmpJsonPath == nullptr) {
815         return false;
816     }
817 
818     if (!BundleUtil::IsFile(tmpJsonPath)) {
819         AdapterFree(tmpJsonPath);
820         return false;
821     }
822 
823     char *jsonPathComp[] = {
824         const_cast<char *>(JSON_PATH), const_cast<char *>(fileName), const_cast<char *>(JSON_SUFFIX)
825     };
826     char *jsonPath = BundleUtil::Strscat(jsonPathComp, sizeof(jsonPathComp) / sizeof(char *));
827     if (jsonPath == nullptr) {
828         AdapterFree(tmpJsonPath);
829         return false;
830     }
831 
832     if (!BundleUtil::RenameFile(tmpJsonPath, jsonPath)) {
833         AdapterFree(jsonPath);
834         AdapterFree(tmpJsonPath);
835         return false;
836     }
837 
838     AdapterFree(jsonPath);
839     AdapterFree(tmpJsonPath);
840     return true;
841 }
842 } // namespace OHOS