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_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
149 while (index < totalFileSize) {
150 if (GtExtractorUtil::ExtractFileAttr(fp, &fileName, &relativeFilePath, fileSize) != ERR_OK) {
151 HILOG_ERROR(HILOG_MODULE_AAFWK, "[BMS] get file attr failed!");
152 UI_Free(fileName);
153 UI_Free(relativeFilePath);
154 break;
155 }
156
157 int32_t fileNameLen = strlen(fileName);
158 if ((strlen(relativeFilePath) == 0 && (strcmp(fileName, PROFILE_NAME) == 0)) ||
159 !BundleUtil::StartWith(relativeFilePath, ASSET_JS_PATH)) {
160 if (!GtExtractorUtil::HasWrittenFile(path, relativeFilePath, fileName, fp, fileSize)) {
161 UI_Free(fileName);
162 UI_Free(relativeFilePath);
163 return false;
164 }
165 } else {
166 int32_t ret = lseek(fp, fileSize, SEEK_CUR);
167 if (ret < 0) {
168 UI_Free(fileName);
169 UI_Free(relativeFilePath);
170 return false;
171 }
172 }
173
174 index = index + INT_LENGTH + fileNameLen + INT_LENGTH + strlen(relativeFilePath) + LONG_LENGTH + fileSize;
175 UI_Free(fileName);
176 UI_Free(relativeFilePath);
177 fileName = nullptr;
178 relativeFilePath = nullptr;
179 }
180 return true;
181 }
182
ExtractInstallMsg(const char * path,char ** bundleName,char ** label,char ** smallIconPath,char ** bigIconPath)183 uint8_t GtBundleExtractor::ExtractInstallMsg(const char *path, char **bundleName, char **label, char **smallIconPath,
184 char **bigIconPath)
185 {
186 if (!BundleUtil::CheckRealPath(path)) {
187 return ERR_APPEXECFWK_INSTALL_FAILED_PARAM_ERROR;
188 }
189 #ifdef _MINI_BMS_
190 int32_t totalFileSize = APPVERI_GetUnsignedFileLength(path);
191 if (totalFileSize == V_ERR) {
192 HILOG_ERROR(HILOG_MODULE_AAFWK, "[BMS] get unsigned file length failed!");
193 return ERR_APPEXECFWK_INSTALL_FAILED_INTERNAL_ERROR;
194 }
195 #else
196 int32_t totalFileSize = BundleUtil::GetFileSize(path);
197 #endif
198 char *emptyJsPathComp[] = {const_cast<char *>(TMP_RESOURCE_DIR), const_cast<char *>(ASSET_JS_PATH)};
199 char *emptyJsPath = BundleUtil::Strscat(emptyJsPathComp, sizeof(emptyJsPathComp) / sizeof(char *));
200 if (emptyJsPath == nullptr) {
201 return ERR_APPEXECFWK_INSTALL_FAILED_INTERNAL_ERROR;
202 }
203
204 if (!BundleUtil::MkDirs(emptyJsPath)) {
205 AdapterFree(emptyJsPath);
206 return ERR_APPEXECFWK_INSTALL_FAILED_CREATE_DATA_DIR_ERROR;
207 }
208 AdapterFree(emptyJsPath);
209
210 int32_t fp = open(path, O_RDONLY, S_IREAD);
211 if (fp < 0) {
212 return ERR_APPEXECFWK_INSTALL_FAILED_FILE_NOT_EXISTS;
213 }
214 // extractor config.json、 resources dir and resources.index in TMP_RESOURCE_DIR
215 if (!ExtractResourceFile(TMP_RESOURCE_DIR, fp, static_cast<uint32_t>(totalFileSize))) {
216 HILOG_ERROR(HILOG_MODULE_AAFWK, "[BMS] extract resource file failed!");
217 close(fp);
218 return ERR_APPEXECFWK_INSTALL_FAILED_PARSE_PROFILE_ERROR;
219 }
220 close(fp);
221 // get bundleName、 label、 smallIconPath and bigIconPath from bundleInfo
222 BundleRes bundleRes = { 0 };
223 BundleInfo *bundleInfo = GtBundleParser::ParseHapProfile(TMP_RESOURCE_DIR, &bundleRes);
224 if (bundleInfo == nullptr) {
225 HILOG_ERROR(HILOG_MODULE_AAFWK, "[BMS] parse hap profile get bundle info failed!");
226 return ERR_APPEXECFWK_INSTALL_FAILED_PARSE_PROFILE_ERROR;
227 }
228 if (bundleRes.abilityRes != nullptr) {
229 AdapterFree(bundleRes.abilityRes);
230 }
231 *bundleName = Utils::Strdup(bundleInfo->bundleName);
232 *label = Utils::Strdup(bundleInfo->label);
233 *smallIconPath = Utils::Strdup(bundleInfo->smallIconPath);
234 *bigIconPath = Utils::Strdup(bundleInfo->bigIconPath);
235 if (*bundleName == nullptr || *label == nullptr || *smallIconPath == nullptr || *bigIconPath == nullptr) {
236 BundleInfoUtils::FreeBundleInfo(bundleInfo);
237 return ERR_APPEXECFWK_INSTALL_FAILED_PARSE_ABILITIES_ERROR;
238 }
239 BundleInfoUtils::FreeBundleInfo(bundleInfo);
240 return ERR_OK;
241 }
242
ExtractBundleParam(const char * path,int32_t & fpStart,char ** bundleName)243 uint8_t GtBundleExtractor::ExtractBundleParam(const char *path, int32_t &fpStart, char **bundleName)
244 {
245 if (!BundleUtil::CheckRealPath(path)) {
246 return ERR_APPEXECFWK_INSTALL_FAILED_PARAM_ERROR;
247 }
248
249 int32_t fp = open(path, O_RDONLY, S_IREAD);
250 if (fp < 0) {
251 return ERR_APPEXECFWK_INSTALL_FAILED_FILE_NOT_EXISTS;
252 }
253 fpStart = fp;
254
255 uint8_t errorCode = GtExtractorUtil::ExtractFileHeaderInfo(fp, bundleName);
256 if (errorCode != ERR_OK) {
257 return errorCode;
258 }
259
260 if (strlen(*bundleName) > MAX_BUNDLE_NAME_LEN || strlen(*bundleName) < MIN_BUNDLE_NAME_LEN) {
261 return ERR_APPEXECFWK_INSTALL_FAILED_PARSE_INVALID_BUNDLENAME_LENGTH;
262 }
263
264 if (strstr(*bundleName, "../") != nullptr) {
265 return ERR_APPEXECFWK_INSTALL_FAILED_PARSE_INVALID_BUNDLENAME;
266 }
267 return ERR_OK;
268 }
269 } // namespace OHOS