1 /*
2 * Copyright (c) 2021-2022 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 "bundle_parser.h"
17
18 #include <fstream>
19 #include <sstream>
20 #include <unistd.h>
21
22 #include "app_log_wrapper.h"
23 #include "app_privilege_capability.h"
24 #include "bundle_constants.h"
25 #include "bundle_extractor.h"
26 #include "bundle_profile.h"
27 #include "default_permission_profile.h"
28 #include "module_profile.h"
29 #include "pre_bundle_profile.h"
30 #include "rpcid_decode/syscap_tool.h"
31 #include "securec.h"
32
33 namespace OHOS {
34 namespace AppExecFwk {
35 namespace {
36 const std::string INSTALL_ABILITY_CONFIGS = "install_ability_configs";
37
ParseStr(const char * buf,const int itemLen,int totalLen,std::vector<std::string> & sysCaps)38 bool ParseStr(const char *buf, const int itemLen, int totalLen, std::vector<std::string> &sysCaps)
39 {
40 APP_LOGD("Parse rpcid output start, itemLen:%{public}d totalLen:%{public}d.", itemLen, totalLen);
41 if (buf == nullptr || itemLen <= 0 || totalLen <= 0) {
42 APP_LOGE("param invalid.");
43 return false;
44 }
45
46 int index = 0;
47 while (index + itemLen <= totalLen) {
48 char item[itemLen];
49 if (strncpy_s(item, sizeof(item), buf + index, itemLen) != 0) {
50 APP_LOGE("Parse rpcid failed due to strncpy_s error.");
51 return false;
52 }
53
54 sysCaps.emplace_back((std::string)item, 0, itemLen);
55 index += itemLen;
56 }
57
58 return true;
59 }
60 } // namespace
61
ReadFileIntoJson(const std::string & filePath,nlohmann::json & jsonBuf)62 bool BundleParser::ReadFileIntoJson(const std::string &filePath, nlohmann::json &jsonBuf)
63 {
64 if (access(filePath.c_str(), F_OK) != 0) {
65 APP_LOGE("can not access the file: %{public}s", filePath.c_str());
66 return false;
67 }
68
69 std::fstream in;
70 char errBuf[256];
71 errBuf[0] = '\0';
72 in.open(filePath, std::ios_base::in);
73 if (!in.is_open()) {
74 strerror_r(errno, errBuf, sizeof(errBuf));
75 APP_LOGE("the file cannot be open due to %{public}s", errBuf);
76 return false;
77 }
78
79 in.seekg(0, std::ios::end);
80 int64_t size = in.tellg();
81 if (size <= 0) {
82 APP_LOGE("the file is an empty file");
83 in.close();
84 return false;
85 }
86
87 in.seekg(0, std::ios::beg);
88 jsonBuf = nlohmann::json::parse(in, nullptr, false);
89 in.close();
90 if (jsonBuf.is_discarded()) {
91 APP_LOGE("bad profile file");
92 return false;
93 }
94
95 return true;
96 }
97
Parse(const std::string & pathName,InnerBundleInfo & innerBundleInfo) const98 ErrCode BundleParser::Parse(
99 const std::string &pathName,
100 InnerBundleInfo &innerBundleInfo) const
101 {
102 APP_LOGI("parse from %{private}s", pathName.c_str());
103 BundleExtractor bundleExtractor(pathName);
104 if (!bundleExtractor.Init()) {
105 APP_LOGE("bundle extractor init failed");
106 return ERR_APPEXECFWK_PARSE_UNEXPECTED;
107 }
108
109 // to extract config.json
110 std::ostringstream outStream;
111 if (!bundleExtractor.ExtractProfile(outStream)) {
112 APP_LOGE("extract profile file failed");
113 return ERR_APPEXECFWK_PARSE_NO_PROFILE;
114 }
115
116 if (bundleExtractor.IsNewVersion()) {
117 APP_LOGD("module.json transform to InnerBundleInfo");
118 innerBundleInfo.SetIsNewVersion(true);
119 ModuleProfile moduleProfile;
120 return moduleProfile.TransformTo(
121 outStream, bundleExtractor, innerBundleInfo);
122 }
123 APP_LOGD("config.json transform to InnerBundleInfo");
124 innerBundleInfo.SetIsNewVersion(false);
125 BundleProfile bundleProfile;
126 ErrCode ret = bundleProfile.TransformTo(
127 outStream, bundleExtractor, innerBundleInfo);
128 if (ret != ERR_OK) {
129 APP_LOGE("transform stream to innerBundleInfo failed %{public}d", ret);
130 return ret;
131 }
132 auto& abilityInfos = innerBundleInfo.FetchAbilityInfos();
133 for (auto& info : abilityInfos) {
134 info.second.isStageBasedModel = bundleExtractor.IsStageBasedModel(info.second.name);
135 auto iter = innerBundleInfo.FetchInnerModuleInfos().find(info.second.package);
136 if (iter != innerBundleInfo.FetchInnerModuleInfos().end()) {
137 iter->second.isStageBasedModel = info.second.isStageBasedModel;
138 }
139 }
140
141 return ERR_OK;
142 }
143
ParsePackInfo(const std::string & pathName,BundlePackInfo & bundlePackInfo) const144 ErrCode BundleParser::ParsePackInfo(const std::string &pathName, BundlePackInfo &bundlePackInfo) const
145 {
146 APP_LOGI("parse from %{private}s", pathName.c_str());
147 BundleExtractor bundleExtractor(pathName);
148 if (!bundleExtractor.Init()) {
149 APP_LOGE("bundle extractor init failed");
150 return ERR_APPEXECFWK_PARSE_UNEXPECTED;
151 }
152
153 // to extract pack.info
154 if (!bundleExtractor.HasEntry(Constants::BUNDLE_PACKFILE_NAME)) {
155 APP_LOGW("cannot find pack.info in the hap file");
156 return ERR_OK;
157 }
158 std::ostringstream outStreamForPackInfo;
159 if (!bundleExtractor.ExtractPackFile(outStreamForPackInfo)) {
160 APP_LOGE("extract profile file failed");
161 return ERR_APPEXECFWK_PARSE_NO_PROFILE;
162 }
163 BundleProfile bundleProfile;
164 ErrCode ret = bundleProfile.TransformTo(outStreamForPackInfo, bundlePackInfo);
165 if (ret != ERR_OK) {
166 APP_LOGE("transform stream to bundlePackinfo failed %{public}d", ret);
167 return ret;
168 }
169 return ERR_OK;
170 }
171
ParseSysCap(const std::string & pathName,std::vector<std::string> & sysCaps) const172 ErrCode BundleParser::ParseSysCap(const std::string &pathName, std::vector<std::string> &sysCaps) const
173 {
174 APP_LOGD("Parse sysCaps from %{private}s", pathName.c_str());
175 BundleExtractor bundleExtractor(pathName);
176 if (!bundleExtractor.Init()) {
177 APP_LOGE("Bundle extractor init failed");
178 return ERR_APPEXECFWK_PARSE_UNEXPECTED;
179 }
180
181 if (!bundleExtractor.HasEntry(Constants::SYSCAP_NAME)) {
182 APP_LOGD("Rpcid.sc is not exist, and do not need verification sysCaps.");
183 return ERR_OK;
184 }
185
186 std::stringstream rpcidStream;
187 if (!bundleExtractor.ExtractByName(Constants::SYSCAP_NAME, rpcidStream)) {
188 APP_LOGE("Extract rpcid file failed");
189 return ERR_APPEXECFWK_PARSE_RPCID_FAILED;
190 }
191
192 int32_t rpcidLen = rpcidStream.tellp();
193 if (rpcidLen < 0) {
194 return ERR_APPEXECFWK_PARSE_UNEXPECTED;
195 }
196 char rpcidBuf[rpcidLen];
197 rpcidStream.read(rpcidBuf, rpcidLen);
198 uint32_t outLen;
199 char *outBuffer;
200 int result = RPCIDStreamDecodeToBuffer(rpcidBuf, rpcidLen, &outBuffer, &outLen);
201 if (result != 0) {
202 APP_LOGE("Decode syscaps failed");
203 return ERR_APPEXECFWK_PARSE_RPCID_FAILED;
204 }
205
206 if (!ParseStr(outBuffer, SINGLE_SYSCAP_LENGTH, outLen, sysCaps)) {
207 APP_LOGE("Parse syscaps str failed");
208 free(outBuffer);
209 return ERR_APPEXECFWK_PARSE_RPCID_FAILED;
210 }
211
212 APP_LOGD("Parse sysCaps str success");
213 free(outBuffer);
214 return ERR_OK;
215 }
216
ParsePreInstallConfig(const std::string & configFile,std::set<PreScanInfo> & scanInfos) const217 ErrCode BundleParser::ParsePreInstallConfig(
218 const std::string &configFile, std::set<PreScanInfo> &scanInfos) const
219 {
220 APP_LOGD("Parse preInstallConfig from %{public}s", configFile.c_str());
221 nlohmann::json jsonBuf;
222 if (!ReadFileIntoJson(configFile, jsonBuf)) {
223 APP_LOGE("Parse preInstallConfig file failed");
224 return ERR_APPEXECFWK_PARSE_FILE_FAILED;
225 }
226
227 PreBundleProfile preBundleProfile;
228 return preBundleProfile.TransformTo(jsonBuf, scanInfos);
229 }
230
ParsePreUnInstallConfig(const std::string & configFile,std::set<std::string> & uninstallList) const231 ErrCode BundleParser::ParsePreUnInstallConfig(
232 const std::string &configFile,
233 std::set<std::string> &uninstallList) const
234 {
235 APP_LOGD("Parse PreUnInstallConfig from %{public}s", configFile.c_str());
236 nlohmann::json jsonBuf;
237 if (!ReadFileIntoJson(configFile, jsonBuf)) {
238 APP_LOGE("Parse preUnInstallConfig file failed");
239 return ERR_APPEXECFWK_PARSE_FILE_FAILED;
240 }
241
242 PreBundleProfile preBundleProfile;
243 return preBundleProfile.TransformTo(jsonBuf, uninstallList);
244 }
245
ParsePreInstallAbilityConfig(const std::string & configFile,std::set<PreBundleConfigInfo> & preBundleConfigInfos) const246 ErrCode BundleParser::ParsePreInstallAbilityConfig(
247 const std::string &configFile, std::set<PreBundleConfigInfo> &preBundleConfigInfos) const
248 {
249 APP_LOGD("Parse PreInstallAbilityConfig from %{public}s", configFile.c_str());
250 nlohmann::json jsonBuf;
251 if (!ReadFileIntoJson(configFile, jsonBuf)) {
252 APP_LOGE("Parse preInstallAbilityConfig file failed");
253 return ERR_APPEXECFWK_PARSE_FILE_FAILED;
254 }
255
256 PreBundleProfile preBundleProfile;
257 return preBundleProfile.TransformTo(jsonBuf, preBundleConfigInfos);
258 }
259
ParseDefaultPermission(const std::string & permissionFile,std::set<DefaultPermission> & defaultPermissions) const260 ErrCode BundleParser::ParseDefaultPermission(
261 const std::string &permissionFile, std::set<DefaultPermission> &defaultPermissions) const
262 {
263 APP_LOGD("Parse DefaultPermission from %{private}s", permissionFile.c_str());
264 nlohmann::json jsonBuf;
265 if (!ReadFileIntoJson(permissionFile, jsonBuf)) {
266 APP_LOGE("Parse default-permissions file failed");
267 return ERR_APPEXECFWK_PARSE_FILE_FAILED;
268 }
269
270 DefaultPermissionProfile profile;
271 return profile.TransformTo(jsonBuf, defaultPermissions);
272 }
273 } // namespace AppExecFwk
274 } // namespace OHOS
275