• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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