1 /*
2 * Copyright (c) 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 "parse_util.h"
17
18 #include <cinttypes>
19 #include <dlfcn.h>
20 #include <fstream>
21 #include <memory>
22 #include <sstream>
23 #include <vector>
24
25 #include "datetime_ex.h"
26 #include "hisysevent_adapter.h"
27 #include "hitrace_meter.h"
28 #include "libxml/globals.h"
29 #include "libxml/tree.h"
30 #include "libxml/xmlstring.h"
31 #include "sam_log.h"
32 #include "string_ex.h"
33
34 namespace OHOS {
35 using std::string;
36
37 namespace {
38 const auto XML_TAG_PROFILE = "profile";
39 const auto XML_TAG_INFO = "info";
40 const auto XML_TAG_SYSTEM_ABILITY = "systemability";
41 const auto XML_TAG_PROCESS = "process";
42 const auto XML_TAG_LIB_PATH = "libpath";
43 const auto XML_TAG_NAME = "name";
44 const auto XML_TAG_DEPEND = "depend";
45 const auto XML_TAG_DEPEND_TIMEOUT = "depend-time-out";
46 const auto XML_TAG_RUN_ON_CREATE = "run-on-create";
47 const auto XML_TAG_DISTRIBUTED = "distributed";
48 const auto XML_TAG_DUMP_LEVEL = "dump-level";
49 const auto XML_TAG_CAPABILITY = "capability";
50 const auto XML_TAG_PERMISSION = "permission";
51 const auto XML_TAG_BOOT_PHASE = "bootphase";
52 const auto XML_TAG_SAID = "said";
53 }
54
~ParseUtil()55 ParseUtil::~ParseUtil()
56 {
57 ClearResource();
58 }
59
CloseHandle(SaProfile & saProfile)60 void ParseUtil::CloseHandle(SaProfile& saProfile)
61 {
62 if (saProfile.handle == nullptr) {
63 return;
64 }
65 int32_t ret = dlclose(saProfile.handle);
66 if (ret) {
67 HILOGW("close handle failed with errno:%{public}d!", errno);
68 }
69 saProfile.handle = nullptr;
70 }
71
CloseSo()72 void ParseUtil::CloseSo()
73 {
74 for (auto& saProfile : saProfiles_) {
75 CloseHandle(saProfile);
76 }
77 }
78
CloseSo(int32_t systemAbilityId)79 void ParseUtil::CloseSo(int32_t systemAbilityId)
80 {
81 for (auto& saProfile : saProfiles_) {
82 if (saProfile.saId == systemAbilityId) {
83 CloseHandle(saProfile);
84 break;
85 }
86 }
87 }
88
ClearResource()89 void ParseUtil::ClearResource()
90 {
91 CloseSo();
92 saProfiles_.clear();
93 }
94
OpenSo()95 void ParseUtil::OpenSo()
96 {
97 for (auto& saProfile : saProfiles_) {
98 if (saProfile.runOnCreate) {
99 OpenSo(saProfile);
100 }
101 }
102 }
103
OpenSo(SaProfile & saProfile)104 void ParseUtil::OpenSo(SaProfile& saProfile)
105 {
106 if (saProfile.handle == nullptr) {
107 std::string dlopenTag = ToString(saProfile.saId) + "_DLOPEN";
108 HITRACE_METER_NAME(HITRACE_TAG_SAMGR, dlopenTag);
109 int64_t begin = GetTickCount();
110 DlHandle handle = dlopen(Str16ToStr8(saProfile.libPath).c_str(), RTLD_NOW);
111 HILOGI("[PerformanceTest] SA:%{public}d OpenSo spend %{public}" PRId64 " ms",
112 saProfile.saId, GetTickCount() - begin);
113 if (handle == nullptr) {
114 std::vector<string> libPathVec;
115 string fileName = "";
116 SplitStr(Str16ToStr8(saProfile.libPath), "/", libPathVec);
117 if ((libPathVec.size() > 0)) {
118 fileName = libPathVec[libPathVec.size() - 1];
119 }
120 ReportAddSystemAbilityFailed(saProfile.saId, fileName);
121 HILOGE("dlopen %{public}s failed with errno:%s!", fileName.c_str(), dlerror());
122 return;
123 }
124 saProfile.handle = handle;
125 } else {
126 HILOGI("SA:%{public}d handle is not null", saProfile.saId);
127 }
128 }
129
LoadSaLib(int32_t systemAbilityId)130 bool ParseUtil::LoadSaLib(int32_t systemAbilityId)
131 {
132 for (auto& saProfile : saProfiles_) {
133 if (saProfile.saId == systemAbilityId) {
134 OpenSo(saProfile);
135 return true;
136 }
137 }
138 return false;
139 }
140
GetAllSaProfiles() const141 const std::list<SaProfile>& ParseUtil::GetAllSaProfiles() const
142 {
143 return saProfiles_;
144 }
145
GetProfile(int32_t saId,SaProfile & saProfile)146 bool ParseUtil::GetProfile(int32_t saId, SaProfile& saProfile)
147 {
148 auto iter = std::find_if(saProfiles_.begin(), saProfiles_.end(), [saId](auto saProfile) {
149 return saProfile.saId == saId;
150 });
151 if (iter != saProfiles_.end()) {
152 saProfile = *iter;
153 return true;
154 }
155 return false;
156 }
157
RemoveSaProfile(int32_t saId)158 void ParseUtil::RemoveSaProfile(int32_t saId)
159 {
160 saProfiles_.remove_if([saId] (auto saInfo) -> bool { return saInfo.saId == saId; });
161 }
162
ParseSAProp(const string & nodeName,const string & nodeContent,SaProfile & saProfile)163 void ParseUtil::ParseSAProp(const string& nodeName, const string& nodeContent, SaProfile& saProfile)
164 {
165 if (nodeName == XML_TAG_NAME) {
166 StrToInt(nodeContent.c_str(), saProfile.saId);
167 } else if (nodeName == XML_TAG_LIB_PATH) {
168 saProfile.libPath = Str8ToStr16(nodeContent);
169 } else if (nodeName == XML_TAG_DEPEND) {
170 saProfile.dependSa.emplace_back(Str8ToStr16(nodeContent));
171 } else if (nodeName == XML_TAG_DEPEND_TIMEOUT) {
172 StrToInt(nodeContent.c_str(), saProfile.dependTimeout);
173 } else if (nodeName == XML_TAG_RUN_ON_CREATE) {
174 std::istringstream(nodeContent) >> std::boolalpha >> saProfile.runOnCreate;
175 } else if (nodeName == XML_TAG_DISTRIBUTED) {
176 std::istringstream(nodeContent) >> std::boolalpha >> saProfile.distributed;
177 } else if (nodeName == XML_TAG_DUMP_LEVEL) {
178 std::stringstream ss(nodeContent);
179 ss >> saProfile.dumpLevel;
180 } else if (nodeName == XML_TAG_CAPABILITY) {
181 saProfile.capability = Str8ToStr16(nodeContent);
182 } else if (nodeName == XML_TAG_PERMISSION) {
183 saProfile.permission = Str8ToStr16(nodeContent);
184 } else if (nodeName == XML_TAG_BOOT_PHASE) {
185 saProfile.bootPhase = Str8ToStr16(nodeContent);
186 }
187 }
188
ParseSystemAbility(const xmlNode & rootNode,const std::u16string & process)189 bool ParseUtil::ParseSystemAbility(const xmlNode& rootNode, const std::u16string& process)
190 {
191 auto currNodePtr = rootNode.xmlChildrenNode;
192 if (currNodePtr == nullptr) {
193 return false;
194 }
195 SaProfile saProfile;
196 saProfile.process = process;
197 for (; currNodePtr != nullptr; currNodePtr = currNodePtr->next) {
198 if (currNodePtr->name == nullptr || currNodePtr->type == XML_COMMENT_NODE) {
199 continue;
200 }
201 auto contentPtr = xmlNodeGetContent(currNodePtr);
202 if (contentPtr == nullptr) {
203 continue;
204 }
205 string nodeName(reinterpret_cast<const char*>(currNodePtr->name));
206 string nodeContent(reinterpret_cast<char*>(contentPtr));
207 ParseSAProp(nodeName, nodeContent, saProfile);
208 xmlFree(contentPtr);
209 }
210 saProfiles_.emplace_back(saProfile);
211 return true;
212 }
213
ParseProcess(const xmlNodePtr & rootNode,std::u16string & processName)214 bool ParseUtil::ParseProcess(const xmlNodePtr& rootNode, std::u16string& processName)
215 {
216 if (rootNode->name == nullptr || rootNode->type == XML_COMMENT_NODE) {
217 return false;
218 }
219 auto contentPtr = xmlNodeGetContent(rootNode);
220 if (contentPtr == nullptr) {
221 return false;
222 }
223 string nodeContent(reinterpret_cast<char*>(contentPtr));
224 processName = Str8ToStr16(nodeContent);
225 xmlFree(contentPtr);
226 return true;
227 }
228
ParseSaProfiles(const string & profilePath)229 bool ParseUtil::ParseSaProfiles(const string& profilePath)
230 {
231 HILOGD("xmlFile:%{private}s", profilePath.c_str());
232 std::string realPath = GetRealPath(profilePath);
233 if (!CheckPathExist(realPath.c_str())) {
234 HILOGE("bad profile path!");
235 return false;
236 }
237 std::unique_ptr<xmlDoc, decltype(&xmlFreeDoc)> ptrDoc(
238 xmlReadFile(realPath.c_str(), nullptr, XML_PARSE_NOBLANKS), xmlFreeDoc);
239
240 if (ptrDoc == nullptr) {
241 HILOGE("xmlReadFile error!");
242 return false;
243 }
244 xmlNodePtr rootNodePtr = xmlDocGetRootElement(ptrDoc.get());
245 if (!CheckRootTag(rootNodePtr)) {
246 HILOGW("wrong root element tag!");
247 return false;
248 }
249 bool isParseCorrect = false;
250 xmlNodePtr currNodePtr = rootNodePtr->xmlChildrenNode;
251 std::u16string process = u"";
252 for (; currNodePtr != nullptr; currNodePtr = currNodePtr->next) {
253 if (currNodePtr->name == nullptr || currNodePtr->type == XML_COMMENT_NODE) {
254 continue;
255 }
256
257 string nodeName(reinterpret_cast<const char*>(currNodePtr->name));
258 HILOGD("profile nodeName:%{public}s", nodeName.c_str());
259 if (nodeName == XML_TAG_PROCESS && process.empty()) {
260 if (!ParseProcess(currNodePtr, process)) {
261 HILOGW("profile %{public}s wrong tag!", currNodePtr->name);
262 return false;
263 }
264 }
265 if (nodeName == XML_TAG_SYSTEM_ABILITY) {
266 if (!ParseSystemAbility(*currNodePtr, process)) {
267 HILOGW("profile %{public}s wrong tag!", currNodePtr->name);
268 return false;
269 }
270 isParseCorrect = true;
271 }
272 }
273 procName_ = process;
274 return isParseCorrect;
275 }
276
GetProcessName() const277 std::u16string ParseUtil::GetProcessName() const
278 {
279 return procName_;
280 }
281
GetRealPath(const string & profilePath) const282 std::string ParseUtil::GetRealPath(const string& profilePath) const
283 {
284 char path[PATH_MAX] = {'\0'};
285 if (realpath(profilePath.c_str(), path) == nullptr) {
286 HILOGE("get real path fail");
287 return "";
288 }
289 std::string realPath(path);
290 return realPath;
291 }
292
CheckPathExist(const string & profilePath)293 bool ParseUtil::CheckPathExist(const string& profilePath)
294 {
295 std::ifstream profileStream(profilePath.c_str());
296 return profileStream.good();
297 }
298
ParseTrustConfig(const string & profilePath,std::map<std::u16string,std::set<int32_t>> & values)299 bool ParseUtil::ParseTrustConfig(const string& profilePath,
300 std::map<std::u16string, std::set<int32_t>>& values)
301 {
302 HILOGD("config path:%{private}s", profilePath.c_str());
303 std::string realPath = GetRealPath(profilePath);
304 if (!CheckPathExist(realPath.c_str())) {
305 HILOGE("bad profile path!");
306 return false;
307 }
308 std::unique_ptr<xmlDoc, decltype(&xmlFreeDoc)> docPtr(
309 xmlReadFile(realPath.c_str(), nullptr, XML_PARSE_NOBLANKS), xmlFreeDoc);
310 if (docPtr == nullptr) {
311 HILOGE("ParseTrustConfig xmlReadFile error!");
312 return false;
313 }
314 xmlNodePtr rootNodePtr = xmlDocGetRootElement(docPtr.get());
315 if (!CheckRootTag(rootNodePtr)) {
316 HILOGW("ParseTrustConfig wrong root element tag!");
317 return false;
318 }
319
320 return ParseTrustConfigInner(rootNodePtr, values);
321 }
322
CheckRootTag(const xmlNodePtr & rootNodePtr)323 bool ParseUtil::CheckRootTag(const xmlNodePtr& rootNodePtr)
324 {
325 if (rootNodePtr == nullptr || rootNodePtr->name == nullptr ||
326 (xmlStrcmp(rootNodePtr->name, reinterpret_cast<const xmlChar*>(XML_TAG_PROFILE)) != 0 &&
327 xmlStrcmp(rootNodePtr->name, reinterpret_cast<const xmlChar*>(XML_TAG_INFO)) != 0)) {
328 return false;
329 }
330 return true;
331 }
332
ParseTrustConfigInner(const xmlNodePtr & rootNodePtr,std::map<std::u16string,std::set<int32_t>> & values)333 bool ParseUtil::ParseTrustConfigInner(const xmlNodePtr& rootNodePtr,
334 std::map<std::u16string, std::set<int32_t>>& values)
335 {
336 xmlNodePtr currNodePtr = rootNodePtr->xmlChildrenNode;
337 if (currNodePtr == nullptr) {
338 return false;
339 }
340 std::u16string processName = u"";
341 for (; currNodePtr != nullptr; currNodePtr = currNodePtr->next) {
342 if (currNodePtr->name == nullptr || currNodePtr->type == XML_COMMENT_NODE) {
343 continue;
344 }
345
346 string nodeName(reinterpret_cast<const char*>(currNodePtr->name));
347 HILOGD("ParseTrustConfigInner profile nodeName:%{public}s", nodeName.c_str());
348
349 if (nodeName == XML_TAG_NAME && processName.empty()) {
350 // parse process name
351 if (!ParseProcess(currNodePtr, processName)) {
352 HILOGE("ParseTrustConfigInner wrong name tag!");
353 return false;
354 }
355 } else if (nodeName == XML_TAG_SAID) {
356 // parse said
357 int32_t saId = -1;
358 if (!ParseSaId(currNodePtr, saId)) {
359 HILOGE("ParseTrustConfigInner wrong said tag!");
360 continue;
361 }
362 auto& saIds = values[processName];
363 saIds.emplace(saId);
364 }
365 }
366 return true;
367 }
368
ParseSaId(const xmlNodePtr & rootNode,int32_t & saId)369 bool ParseUtil::ParseSaId(const xmlNodePtr& rootNode, int32_t& saId)
370 {
371 if (rootNode->name == nullptr || rootNode->type == XML_COMMENT_NODE) {
372 return false;
373 }
374 auto contentPtr = xmlNodeGetContent(rootNode);
375 if (contentPtr == nullptr) {
376 return false;
377 }
378 string nodeContent(reinterpret_cast<char*>(contentPtr));
379 bool ret = StrToInt(nodeContent.c_str(), saId);
380 xmlFree(contentPtr);
381 return ret;
382 }
383 } // namespace OHOS
384