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