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 }