1 /*
2  * Copyright (c) 2023 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 "hiview_listener.h"
17 
18 #include <unordered_set>
19 
20 #include "database_manager.h"
21 #include "security_guard_log.h"
22 #include "security_guard_utils.h"
23 
24 namespace OHOS::Security::SecurityGuard {
25 namespace {
26     constexpr int CONTENT_MAX_LEN = 900;
27     constexpr int64_t PASTEBOARD_EVENT_ID = 1011015000;
28     constexpr int64_t BUNDLE_INSTALL_EVENT_ID = 0x818800800;
29     constexpr int64_t BUNDLE_UPDATE_EVENT_ID = 0x818800801;
30     const std::unordered_set<std::string> HAP_INSTALL_UPDATE_STR = {"USERID", "BUNDLE_NAME",
31         "VERSION", "APP_DISTRIBUTION_TYPE", "INSTALL_TIME", "CALLING_UID", "CALLING_APPID",
32         "CALLING_BUNDLE_NAME", "FINGERPRINT", "HIDE_DESKTOP_ICON", "INSTALL_TYPE", "HASH_VALUE"};
33 }
34 
OnEvent(std::shared_ptr<HiviewDFX::HiSysEventRecord> sysEvent)35 void HiviewListener::OnEvent(std::shared_ptr<HiviewDFX::HiSysEventRecord> sysEvent)
36 {
37     if (sysEvent == nullptr) {
38         return;
39     }
40     SGLOGD("Hiview OnEvent: %{public}s", sysEvent->AsJson().c_str());
41     SecEvent event;
42     if (!GetSecEvent(sysEvent, event)) {
43         SGLOGE("Unknown event");
44         return;
45     }
46     DatabaseManager::GetInstance().InsertEvent(HIVIEW_SOURCE, event);
47 }
48 
OnServiceDied()49 void HiviewListener::OnServiceDied()
50 {
51     SGLOGI("Hiview service disconnect");
52 }
53 
GetSecEvent(std::shared_ptr<HiviewDFX::HiSysEventRecord> sysEvent,SecEvent & event)54 bool HiviewListener::GetSecEvent(std::shared_ptr<HiviewDFX::HiSysEventRecord> sysEvent, SecEvent& event)
55 {
56     std::unordered_map<std::string, int64_t> domainName2Id = {
57         {"PASTEBOARD-USE_BEHAVIOUR", PASTEBOARD_EVENT_ID},
58         {"BUNDLE_MANAGER-BUNDLE_INSTALL", BUNDLE_INSTALL_EVENT_ID},
59         {"BUNDLE_MANAGER-BUNDLE_UPDATE", BUNDLE_UPDATE_EVENT_ID}
60     };
61     std::string domainName = sysEvent->GetDomain() + "-" + sysEvent->GetEventName();
62     if (domainName2Id.count(domainName) == 0) {
63         SGLOGE("The eventId is not applied for");
64         return false;
65     }
66 
67     std::string eventJsonStr = sysEvent->AsJson();
68     if (eventJsonStr.empty() || !nlohmann::json::accept(eventJsonStr)) {
69         SGLOGE("eventJsonStr err");
70         return false;
71     }
72     nlohmann::json eventJson = nlohmann::json::parse(eventJsonStr);
73     if (eventJson.is_discarded()) {
74         SGLOGE("json err");
75         return false;
76     }
77 
78     int64_t sysEventId = domainName2Id[domainName];
79     filterInstallOrUpdateContent(sysEventId, eventJson);
80     if (eventJson.dump().size() >= CONTENT_MAX_LEN) {
81         SGLOGE("The JSON length is too long.");
82         return false;
83     }
84 
85     event = {
86         .eventId = sysEventId,
87         .version = "1.0",
88         .date = SecurityGuardUtils::GetDate(),
89         .content = eventJson.dump()
90     };
91     return true;
92 }
93 
filterInstallOrUpdateContent(int64_t eventId,nlohmann::json & jsonObj)94 void HiviewListener::filterInstallOrUpdateContent(int64_t eventId, nlohmann::json& jsonObj)
95 {
96     if ((eventId != BUNDLE_INSTALL_EVENT_ID) && (eventId != BUNDLE_UPDATE_EVENT_ID)) {
97         return;
98     }
99     if (!filterHashValue(jsonObj)) {
100         return;
101     }
102     for (auto it = jsonObj.begin(); it != jsonObj.end();) {
103         if (HAP_INSTALL_UPDATE_STR.find(it.key()) == HAP_INSTALL_UPDATE_STR.end()) {
104             it = jsonObj.erase(it);
105         } else {
106             ++it;
107         }
108     }
109 }
110 
filterHashValue(nlohmann::json & jsonObj)111 bool HiviewListener::filterHashValue(nlohmann::json& jsonObj)
112 {
113     if (jsonObj.contains("FILE_PATH") && jsonObj.contains("HASH_VALUE")) {
114         bool isFindHap = false;
115         size_t index = 0;
116         const auto& filePath = jsonObj["FILE_PATH"];
117         for (size_t i = 0; i < filePath.size(); i++) {
118             const std::string& path = filePath[i];
119             if (path.find(".hap") != std::string::npos) {
120                 isFindHap = true;
121                 index = i;
122                 break;
123             }
124         }
125         if (!isFindHap || (jsonObj["HASH_VALUE"].size() <= index)) {
126             SGLOGE("Failed to find the hash value of hap");
127             return false;
128         }
129         jsonObj["HASH_VALUE"] = jsonObj["HASH_VALUE"][index];
130     }
131     return true;
132 }
133 } // OHOS::Security::SecurityGuard