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 "data_collection.h"
17 
18 #include "json_cfg.h"
19 #include "security_collector_log.h"
20 #include "collector_cfg_marshalling.h"
21 #include "i_collector.h"
22 
23 namespace OHOS::Security::SecurityCollector {
24 namespace {
25     const char* SA_CONFIG_PATH = "/system/etc/security_audit.cfg";
26 }
27 
GetInstance()28 DataCollection &DataCollection::GetInstance()
29 {
30     static DataCollection instance;
31     return instance;
32 }
33 
StartCollectors(const std::vector<int64_t> & eventIds,std::shared_ptr<ICollectorFwk> api)34 bool DataCollection::StartCollectors(const std::vector<int64_t>& eventIds, std::shared_ptr<ICollectorFwk> api)
35 {
36     LOGI("StartCollectors start");
37     if (eventIds.empty() || !api) {
38         LOGE("Invalid input parameter");
39         return false;
40     }
41     std::vector<int64_t> loadedEventIds_;
42     for (int64_t eventId : eventIds) {
43         LOGI("StartCollectors eventId is %{public}" PRId64 "", eventId);
44         if (IsCollectorStarted(eventId)) {
45             LOGI("Collector already started, eventId is %{public}" PRId64 "", eventId);
46             continue;
47         }
48         std::string collectorPath;
49         ErrorCode ret = GetCollectorPath(eventId, collectorPath);
50         if (ret != SUCCESS) {
51             LOGE("GetCollectorPath failed, eventId is %{public}" PRId64 "", eventId);
52             StopCollectors(loadedEventIds_);
53             return false;
54         }
55         ret = LoadCollector(eventId, collectorPath, api);
56         if (ret != SUCCESS) {
57             LOGE("Load collector failed, eventId is %{public}" PRId64 "", eventId);
58             StopCollectors(loadedEventIds_);
59             return false;
60         }
61         loadedEventIds_.push_back(eventId);
62     }
63     LOGI("StartCollectors finish");
64     return true;
65 }
66 
SecurityGuardSubscribeCollector(const std::vector<int64_t> & eventIds)67 bool DataCollection::SecurityGuardSubscribeCollector(const std::vector<int64_t>& eventIds)
68 {
69     LOGI("Start to subscribe collectors start");
70     std::vector<int64_t> loadedEventIds_;
71     for (int64_t eventId : eventIds) {
72         LOGI("StartCollectors eventId is %{public}" PRId64 "", eventId);
73         if (IsCollectorStarted(eventId)) {
74             LOGI("Collector already started, eventId is %{public}" PRId64 "", eventId);
75             continue;
76         }
77         std::string collectorPath;
78         ErrorCode ret = GetCollectorPath(eventId, collectorPath);
79         if (ret != SUCCESS) {
80             LOGE("GetCollectorPath failed, eventId is %{public}" PRId64 "", eventId);
81             return false;
82         }
83         ret = LoadCollector(eventId, collectorPath, nullptr);
84         if (ret != SUCCESS) {
85             LOGE("GetCollectorPath failed, eventId is %{public}" PRId64 "", eventId);
86             return false;
87         }
88         loadedEventIds_.push_back(eventId);
89     }
90     LOGI("StartCollectors finish");
91     return true;
92 }
93 
IsCollectorStarted(int64_t eventId)94 bool DataCollection::IsCollectorStarted(int64_t eventId)
95 {
96     std::lock_guard<std::mutex> lock(mutex_);
97     auto it = eventIdToLoaderMap_.find(eventId);
98     return it != eventIdToLoaderMap_.end();
99 }
100 
StopCollectors(const std::vector<int64_t> & eventIds)101 bool DataCollection::StopCollectors(const std::vector<int64_t>& eventIds)
102 {
103     LOGI("StopCollectors start");
104     if (eventIds.empty()) {
105         LOGW("The eventId list is empty");
106         return true;
107     }
108     bool ret = true;
109     std::lock_guard<std::mutex> lock(mutex_);
110     for (int64_t eventId : eventIds) {
111         LOGI("StopCollectors eventId is %{public}" PRId64 "", eventId);
112         auto loader = eventIdToLoaderMap_.find(eventId);
113         if (loader == eventIdToLoaderMap_.end()) {
114             LOGI("Collector not found, eventId is %{public}" PRId64 "", eventId);
115             continue;
116         }
117         ICollector* collector = loader->second->CallGetCollector();
118         if (collector == nullptr) {
119             LOGE("CallGetCollector error");
120             ret = false;
121         } else {
122             int result = collector->Stop();
123             int isStartWithSub = collector->IsStartWithSub();
124             if (isStartWithSub == 1) {
125                 result = collector->Unsubscribe(eventId);
126             }
127             if (result != 0) {
128                 LOGE("Failed to stop collector, eventId is %{public}" PRId64 "", eventId);
129                 ret = false;
130             }
131             LOGI("Stop collector");
132             eventIdToLoaderMap_.erase(loader);
133         }
134     }
135     LOGI("StopCollectors finish");
136     return ret;
137 }
138 
LoadCollector(int64_t eventId,std::string path,std::shared_ptr<ICollectorFwk> api)139 ErrorCode DataCollection::LoadCollector(int64_t eventId, std::string path, std::shared_ptr<ICollectorFwk> api)
140 {
141     LOGI("Start LoadCollector");
142     std::unique_ptr<LibLoader> loader = std::make_unique<LibLoader>(path);
143     ErrorCode ret = loader->LoadLib();
144     if (ret != SUCCESS) {
145         LOGE("LoadLib error, ret=%{public}d, path : %{public}s", ret, path.c_str());
146         return FAILED;
147     }
148     ICollector* collector = loader->CallGetCollector();
149     if (collector == nullptr) {
150         LOGE("CallGetCollector error");
151         return FAILED;
152     }
153     int result = collector->Start(api);
154     int isStartWithSub = collector->IsStartWithSub();
155     if (isStartWithSub == 1) {
156         result = collector->Subscribe(eventId);
157     }
158     if (result != 0) {
159         LOGE("Failed to start collector");
160         return FAILED;
161     }
162     std::lock_guard<std::mutex> lock(mutex_);
163     eventIdToLoaderMap_[eventId] = std::move(loader);
164     LOGI("End LoadCollector");
165     return SUCCESS;
166 }
167 
GetCollectorPath(int64_t eventId,std::string & path)168 ErrorCode DataCollection::GetCollectorPath(int64_t eventId, std::string& path)
169 {
170     LOGI("Start GetCollectorPath");
171     std::ifstream stream(SA_CONFIG_PATH, std::ios::in);
172     if (!stream.is_open() || !stream) {
173         LOGE("Stream error, %{public}s", strerror(errno));
174         return STREAM_ERROR;
175     }
176     ErrorCode ret = CheckFileStream(stream);
177     if (ret != SUCCESS) {
178         LOGE("check file stream error, ret=%{public}d", ret);
179         stream.close();
180         return ret;
181     }
182     nlohmann::json json = nlohmann::json::parse(stream, nullptr, false);
183     stream.close();
184 
185     if (json.is_discarded()) {
186         LOGE("json is discarded");
187         return JSON_ERR;
188     }
189 
190     std::vector<ModuleCfgSt> moduleCfgs;
191     if (!SecurityGuard::JsonCfg::Unmarshal<ModuleCfgSt>(moduleCfgs, json, MODULES)) {
192         LOGE("Unmarshal moduleCfgs error");
193         return JSON_ERR;
194     }
195 
196     auto it = std::find_if(moduleCfgs.begin(), moduleCfgs.end(),
197         [eventId] (const ModuleCfgSt &module) {
198             auto ifIt = std::find(module.eventId.begin(), module.eventId.end(), eventId);
199             if (ifIt != module.eventId.end()) {
200                 LOGI("seccess to find the %{public}" PRId64 "", eventId);
201                 return true;
202             } else {
203                 LOGI("Failed to find the eventId");
204                 return false;
205             }
206         });
207     if (it != moduleCfgs.end()) {
208         path = it->modulePath + it->moduleName;
209         return SUCCESS;
210     }
211 
212     LOGE("The eventId does not exist");
213     return FAILED;
214 }
215 
GetCollectorType(int64_t eventId,int32_t & collectorType)216 ErrorCode DataCollection::GetCollectorType(int64_t eventId, int32_t& collectorType)
217 {
218     LOGI("Start GetCollectorType");
219     std::ifstream stream(SA_CONFIG_PATH, std::ios::in);
220     if (!stream.is_open() || !stream) {
221         LOGE("Stream error, %{public}s", strerror(errno));
222         return STREAM_ERROR;
223     }
224 
225     ErrorCode ret = CheckFileStream(stream);
226     if (ret != SUCCESS) {
227         LOGE("check file stream error, ret=%{public}d", ret);
228         stream.close();
229         return ret;
230     }
231 
232     nlohmann::json json = nlohmann::json::parse(stream, nullptr, false);
233     stream.close();
234 
235     if (json.is_discarded()) {
236         LOGE("json is discarded");
237         return JSON_ERR;
238     }
239 
240     std::vector<ModuleCfgSt> moduleCfgs;
241     if (!SecurityGuard::JsonCfg::Unmarshal<ModuleCfgSt>(moduleCfgs, json, MODULES)) {
242         LOGE("Unmarshal moduleCfgs error");
243         return JSON_ERR;
244     }
245 
246     auto it = std::find_if(moduleCfgs.begin(), moduleCfgs.end(),
247         [eventId] (const ModuleCfgSt &module) {
248             auto ifIt = std::find(module.eventId.begin(), module.eventId.end(), eventId);
249             if (ifIt != module.eventId.end()) {
250                 return true;
251             } else {
252                 return false;
253             }
254         });
255     if (it != moduleCfgs.end()) {
256         collectorType = it->collectorType;
257         LOGI("get event %{public}" PRId64 " collector type is %{public}d.", eventId, collectorType);
258         return SUCCESS;
259     }
260 
261     LOGE("The eventId does not exist");
262     return FAILED;
263 }
264 
CheckFileStream(std::ifstream & stream)265 ErrorCode DataCollection::CheckFileStream(std::ifstream &stream)
266 {
267     if (!stream.is_open()) {
268         LOGE("stream open error, %{public}s", strerror(errno));
269         return STREAM_ERROR;
270     }
271 
272     stream.seekg(0, std::ios::end);
273     int len = static_cast<int>(stream.tellg());
274     if (len == 0) {
275         LOGE("stream is empty");
276         return STREAM_ERROR;
277     }
278     stream.seekg(0, std::ios::beg);
279     return SUCCESS;
280 }
281 
LoadCollector(std::string path,const SecurityEventRuler & ruler,std::vector<SecurityEvent> & events)282 ErrorCode DataCollection::LoadCollector(std::string path, const SecurityEventRuler &ruler,
283     std::vector<SecurityEvent> &events)
284 {
285     LOGI("Start LoadCollector");
286     std::unique_ptr<LibLoader> loader = std::make_unique<LibLoader>(path);
287     ErrorCode ret = loader->LoadLib();
288     if (ret != SUCCESS) {
289         LOGE("LoadLib error, ret=%{public}d", ret);
290         return FAILED;
291     }
292     ICollector* collector = loader->CallGetCollector();
293     if (collector == nullptr) {
294         LOGE("CallGetCollector error");
295         return FAILED;
296     }
297     int result = collector->Query(ruler, events);
298     if (result != 0) {
299         LOGE("Failed to start collector");
300         return FAILED;
301     }
302     LOGI("End LoadCollector");
303     return SUCCESS;
304 }
305 
QuerySecurityEvent(const std::vector<SecurityEventRuler> rulers,std::vector<SecurityEvent> & events)306 int32_t DataCollection::QuerySecurityEvent(const std::vector<SecurityEventRuler> rulers,
307     std::vector<SecurityEvent> &events)
308 {
309     LOGI("QuerySecurityEvent start");
310     if (rulers.empty()) {
311         LOGE("Invalid input parameter");
312         return false;
313     }
314     for (const auto &ruler : rulers) {
315         LOGI("QuerySecurityEvent eventId is %{public}" PRId64 "", ruler.GetEventId());
316         std::string collectorPath;
317         ErrorCode ret = GetCollectorPath(ruler.GetEventId(), collectorPath);
318         if (ret != SUCCESS) {
319             LOGE("GetCollectorPath failed, eventId is %{public}" PRId64 "", ruler.GetEventId());
320             return false;
321         }
322         ret = LoadCollector(collectorPath, ruler, events);
323         if (ret != SUCCESS) {
324             LOGE("Load collector failed, eventId is %{public}" PRId64 "", ruler.GetEventId());
325             return false;
326         }
327     }
328     LOGI("StartCollectors finish");
329     return true;
330 }
331 }