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