1 /*
2  * Copyright (c) 2020-2023 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_extractor.h"
17 #include "app_verify_pub.h"
18 
19 #ifdef __cplusplus
20 extern "C" {
21 #endif
22 #ifdef __cplusplus
23 }
24 #endif
25 #include "adapter.h"
26 #include "appexecfwk_errors.h"
27 #include "bundle_util.h"
28 #include "bundlems_log.h"
29 #include "fcntl.h"
30 #include "gt_bundle_manager_service.h"
31 #include "gt_bundle_parser.h"
32 #include "gt_extractor_util.h"
33 #include "sys/stat.h"
34 #include "unistd.h"
35 #include "utils.h"
36 
37 namespace OHOS {
ExtractFileDataPos(int32_t fp,uint64_t & filePos)38 uint8_t GtBundleExtractor::ExtractFileDataPos(int32_t fp, uint64_t &filePos)
39 {
40     char *bundleName = nullptr;
41 
42     int32_t ret = lseek(fp, 0, SEEK_SET);
43     if (ret < 0) {
44         return ERR_APPEXECFWK_INSTALL_FAILED_INTERNAL_ERROR;
45     }
46 
47     uint8_t errorCode = GtExtractorUtil::ExtractFileHeaderInfo(fp, &bundleName);
48     if (errorCode != ERR_OK) {
49         return errorCode;
50     }
51 
52     filePos = MAGIC_NUMBER_LEN + INT_LENGTH + strlen(bundleName);
53     UI_Free(bundleName);
54     return ERR_OK;
55 }
56 
ExtractHap(const char * codePath,const char * bundleName,int32_t fp,uint32_t totalFileSize,uint8_t bundleStyle)57 uint8_t GtBundleExtractor::ExtractHap(const char *codePath, const char *bundleName, int32_t fp, uint32_t totalFileSize,
58     uint8_t bundleStyle)
59 {
60     char *relativeFilePath = nullptr;
61     char *fileName = nullptr;
62     uint64_t fileSize = 0;
63     uint64_t index = 0;
64 
65     if (codePath == nullptr || bundleName == nullptr) {
66         return ERR_APPEXECFWK_INSTALL_FAILED_INTERNAL_ERROR;
67     }
68 
69     uint8_t errorCode = ExtractFileDataPos(fp, index);
70     if (errorCode != ERR_OK) {
71         return errorCode;
72     }
73 
74     while (index < totalFileSize) {
75         errorCode = GtExtractorUtil::ExtractFileToPath(codePath, fp, fileSize, &fileName, &relativeFilePath);
76         if (errorCode != ERR_OK) {
77             UI_Free(relativeFilePath);
78             UI_Free(fileName);
79             break;
80         }
81         index = index + INT_LENGTH + strlen(fileName) + INT_LENGTH + strlen(relativeFilePath) + LONG_LENGTH + fileSize;
82         UI_Free(relativeFilePath);
83         UI_Free(fileName);
84         relativeFilePath = nullptr;
85         fileName = nullptr;
86     }
87     return ERR_OK;
88 }
89 
ExtractHapProfile(int32_t fp,uint32_t totalFileSize)90 char *GtBundleExtractor::ExtractHapProfile(int32_t fp, uint32_t totalFileSize)
91 {
92     char *fileName = nullptr;
93     char *fileData = nullptr;
94     uint64_t fileSize = 0;
95     uint64_t index = 0;
96     uint32_t pathLen = 0;
97 
98     uint8_t errorCode = ExtractFileDataPos(fp, index);
99     if (errorCode != ERR_OK) {
100         HILOG_ERROR(HILOG_MODULE_AAFWK, "[BMS] get file data pos failed!");
101         return nullptr;
102     }
103 
104     while (index < totalFileSize) {
105         if (GtExtractorUtil::ExtractFileAttr(fp, &fileName, pathLen, fileSize) != ERR_OK) {
106             HILOG_ERROR(HILOG_MODULE_AAFWK, "[BMS] get file attr failed!");
107             UI_Free(fileName);
108             return nullptr;
109         }
110 
111         int32_t fileNameLen = strlen(fileName);
112         if (pathLen == 0 && (strcmp(fileName, PROFILE_NAME) == 0)) {
113             UI_Free(fileName);
114             fileName = nullptr;
115             fileData = reinterpret_cast<char *>(AdapterMalloc(fileSize * sizeof(char)));
116             if (fileData == nullptr || read(fp, fileData, fileSize) != fileSize) {
117                 HILOG_ERROR(HILOG_MODULE_AAFWK, "[BMS] get profile data failed!");
118                 AdapterFree(fileData);
119                 return nullptr;
120             }
121             return fileData;
122         } else {
123             UI_Free(fileName);
124             fileName = nullptr;
125             int32_t ret = lseek(fp, fileSize, SEEK_CUR);
126             if (ret < 0) {
127                 return nullptr;
128             }
129         }
130 
131         index = index + INT_LENGTH + fileNameLen + INT_LENGTH + pathLen + LONG_LENGTH + fileSize;
132     }
133     return nullptr;
134 }
135 
ExtractResourceFile(const char * path,int32_t fp,uint32_t totalFileSize)136 bool GtBundleExtractor::ExtractResourceFile(const char *path, int32_t fp, uint32_t totalFileSize)
137 {
138     char *fileName = nullptr;
139     char *relativeFilePath = nullptr;
140     uint64_t fileSize = 0;
141     uint64_t index = 0;
142 
143     uint8_t errorCode = ExtractFileDataPos(fp, index);
144     if (errorCode != ERR_OK) {
145         HILOG_ERROR(HILOG_MODULE_AAFWK, "[BMS] extract file data pos failed!");
146         return false;
147     }
148 #ifdef _MINI_BMS_PERMISSION_
149     RefreshAllServiceTimeStamp();
150 #endif
151     while (index < totalFileSize) {
152         if (GtExtractorUtil::ExtractFileAttr(fp, &fileName, &relativeFilePath, fileSize) != ERR_OK) {
153             HILOG_ERROR(HILOG_MODULE_AAFWK, "[BMS] get file attr failed!");
154             UI_Free(fileName);
155             UI_Free(relativeFilePath);
156             break;
157         }
158 
159         int32_t fileNameLen = strlen(fileName);
160         if ((strlen(relativeFilePath) == 0 && (strcmp(fileName, PROFILE_NAME) == 0)) ||
161             (!BundleUtil::StartWith(relativeFilePath, ASSET_JS_PATH) &&
162             !BundleUtil::StartWith(relativeFilePath, NEW_ASSET_JS_PATH))) {
163             if (!GtExtractorUtil::HasWrittenFile(path, relativeFilePath, fileName, fp, fileSize)) {
164                 UI_Free(fileName);
165                 UI_Free(relativeFilePath);
166                 return false;
167             }
168         } else {
169             int32_t ret = lseek(fp, fileSize, SEEK_CUR);
170             if (ret < 0) {
171                 UI_Free(fileName);
172                 UI_Free(relativeFilePath);
173                 return false;
174             }
175         }
176 
177         index = index + INT_LENGTH + fileNameLen + INT_LENGTH + strlen(relativeFilePath) + LONG_LENGTH + fileSize;
178         UI_Free(fileName);
179         UI_Free(relativeFilePath);
180         fileName = nullptr;
181         relativeFilePath = nullptr;
182     }
183     return true;
184 }
185 
ExtractInstallMsg(const char * path,char ** bundleName,char ** label,char ** smallIconPath,char ** bigIconPath,uint8_t & actionService)186 uint8_t GtBundleExtractor::ExtractInstallMsg(
187     const char *path, char **bundleName, char **label, char **smallIconPath, char **bigIconPath, uint8_t &actionService)
188 {
189 #ifdef _MINI_BMS_PERMISSION_
190     RefreshAllServiceTimeStamp();
191 #endif
192     if (!BundleUtil::CheckRealPath(path)) {
193         return ERR_APPEXECFWK_INSTALL_FAILED_PARAM_ERROR;
194     }
195 #ifdef _MINI_BMS_
196     int32_t totalFileSize = APPVERI_GetUnsignedFileLength(path);
197     if (totalFileSize == V_ERR) {
198         HILOG_ERROR(HILOG_MODULE_AAFWK, "[BMS] get unsigned file length failed!");
199         return ERR_APPEXECFWK_INSTALL_FAILED_INTERNAL_ERROR;
200     }
201 #else
202     int32_t totalFileSize = BundleUtil::GetFileSize(path);
203 #endif
204 
205     int32_t fp = open(path, O_RDONLY, S_IREAD);
206     if (fp < 0) {
207         return ERR_APPEXECFWK_INSTALL_FAILED_FILE_NOT_EXISTS;
208     }
209     // extractor config.json、 resources dir and resources.index in TMP_RESOURCE_DIR
210     if (!ExtractResourceFile(TMP_RESOURCE_DIR, fp, static_cast<uint32_t>(totalFileSize))) {
211         HILOG_ERROR(HILOG_MODULE_AAFWK, "[BMS] extract resource file failed!");
212         close(fp);
213         return ERR_APPEXECFWK_INSTALL_FAILED_PARSE_PROFILE_ERROR;
214     }
215     close(fp);
216     // get bundleName、 label、 smallIconPath and bigIconPath from bundleInfo
217     BundleRes bundleRes = { 0 };
218     BundleInfo *bundleInfo = GtBundleParser::ParseHapProfile(TMP_RESOURCE_DIR, &bundleRes);
219     if (bundleInfo == nullptr) {
220         HILOG_ERROR(HILOG_MODULE_AAFWK, "[BMS] parse hap profile get bundle info failed!");
221         return ERR_APPEXECFWK_INSTALL_FAILED_PARSE_PROFILE_ERROR;
222     }
223     if (bundleRes.abilityRes != nullptr) {
224         AdapterFree(bundleRes.abilityRes);
225     }
226     *bundleName = Utils::Strdup(bundleInfo->bundleName);
227     *label = Utils::Strdup(bundleInfo->label);
228     *smallIconPath = Utils::Strdup(bundleInfo->smallIconPath);
229     *bigIconPath = Utils::Strdup(bundleInfo->bigIconPath);
230     // find bundleInfo->abilityInfo->skills[i]->actions whether contain HOST_APDU_SERVICE
231     actionService = FindSkillService(bundleInfo->abilityInfo);
232     if (*bundleName == nullptr || *label == nullptr || *smallIconPath == nullptr || *bigIconPath == nullptr) {
233         BundleInfoUtils::FreeBundleInfo(bundleInfo);
234         return ERR_APPEXECFWK_INSTALL_FAILED_PARSE_ABILITIES_ERROR;
235     }
236     BundleInfoUtils::FreeBundleInfo(bundleInfo);
237     return ERR_OK;
238 }
239 
ParseBundleInfoGetActionService(const char * bundleName)240 uint8_t GtBundleExtractor::ParseBundleInfoGetActionService(const char *bundleName)
241 {
242     if (bundleName == nullptr) {
243         return ERR_OK;
244     }
245     BundleInfo *bundleInfo = OHOS::GtManagerService::GetInstance().QueryBundleInfo(bundleName);
246     if (bundleInfo == nullptr) {
247         return ERR_OK;
248     }
249     // find bundleInfo->abilityInfo->skills[i]->actions whether contain HOST_APDU_SERVICE
250     uint8_t actionService = FindSkillService(bundleInfo->abilityInfo);
251     return actionService;
252 }
FindSkillService(AbilityInfo * abilityInfo)253 uint8_t GtBundleExtractor::FindSkillService(AbilityInfo *abilityInfo)
254 {
255     if (abilityInfo == nullptr) {
256         return 0;
257     }
258     for (int i = 0; i < SKILL_SIZE; i++) {
259         if (abilityInfo->skills[i] != nullptr) {
260             if (CompareStringArray(abilityInfo->skills[i]->actions, MAX_SKILL_ITEM)) {
261                 return 1;
262             }
263         }
264     }
265     return 0;
266 }
CompareStringArray(char * actions[],int count)267 uint8_t GtBundleExtractor::CompareStringArray(char *actions[], int count)
268 {
269     for (int i = 0; i < count; i++) {
270         if (actions[i] == nullptr) {
271             continue;
272         }
273         if (strcmp(actions[i], SERVICE_NAME) == 0) {
274             return 1;
275         }
276     }
277     return 0;
278 }
279 
ExtractBundleParam(const char * path,int32_t & fpStart,char ** bundleName)280 uint8_t GtBundleExtractor::ExtractBundleParam(const char *path, int32_t &fpStart, char **bundleName)
281 {
282     if (!BundleUtil::CheckRealPath(path)) {
283         return ERR_APPEXECFWK_INSTALL_FAILED_PARAM_ERROR;
284     }
285 
286     int32_t fp = open(path, O_RDONLY, S_IREAD);
287     if (fp < 0) {
288         return ERR_APPEXECFWK_INSTALL_FAILED_FILE_NOT_EXISTS;
289     }
290     fpStart = fp;
291 
292     uint8_t errorCode = GtExtractorUtil::ExtractFileHeaderInfo(fp, bundleName);
293     if (errorCode != ERR_OK) {
294         return errorCode;
295     }
296 
297     if (strlen(*bundleName) > MAX_BUNDLE_NAME_LEN || strlen(*bundleName) < MIN_BUNDLE_NAME_LEN) {
298         return ERR_APPEXECFWK_INSTALL_FAILED_PARSE_INVALID_BUNDLENAME_LENGTH;
299     }
300 
301     if (strstr(*bundleName, "../") != nullptr) {
302         return ERR_APPEXECFWK_INSTALL_FAILED_PARSE_INVALID_BUNDLENAME;
303     }
304     return ERR_OK;
305 }
306 } // namespace OHOS