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 "audit_event_mem_rdb_helper.h"
17 
18 #include "rdb_predicates.h"
19 
20 #include "audit_event_rdb_helper.h"
21 #include "config_data_manager.h"
22 #include "config_define.h"
23 #include "rdb_event_store_callback.h"
24 #include "security_guard_define.h"
25 #include "security_guard_log.h"
26 #include "security_guard_utils.h"
27 
28 namespace OHOS::Security::SecurityGuard {
29 namespace {
30     constexpr uint32_t FLUSH_INTERVAL = 60 * 1000;
31     constexpr uint32_t DELETE_INTERVAL = 10000; // 1 hour
32 }
33 
GetInstance()34 DatabaseHelper &AuditEventMemRdbHelper::GetInstance()
35 {
36     static AuditEventMemRdbHelper auditMemInstance;
37     static DatabaseHelper &instance = auditMemInstance;
38     return instance;
39 }
40 
AuditEventMemRdbHelper()41 AuditEventMemRdbHelper::AuditEventMemRdbHelper() : DatabaseHelper("audit_event_mem")
42 {
43     dbPath_ = FOLDER_PATH + "audit_event_mem.db";
44 }
45 
~AuditEventMemRdbHelper()46 AuditEventMemRdbHelper::~AuditEventMemRdbHelper()
47 {
48     Release();
49 }
50 
Init()51 int AuditEventMemRdbHelper::Init()
52 {
53     int errCode = NativeRdb::E_ERROR;
54     NativeRdb::RdbStoreConfig config(dbPath_);
55     config.SetStorageMode(NativeRdb::StorageMode::MODE_MEMORY);
56     config.SetSecurityLevel(NativeRdb::SecurityLevel::S2);
57     std::string table = CreateTable();
58     std::vector<std::string> createTableVec;
59     createTableVec.push_back(table);
60     RdbEventStoreCallback callback(createTableVec);
61     CreateRdbStore(config, DB_VERSION, callback, errCode);
62     if (errCode != NativeRdb::E_OK) {
63         SGLOGE("create rdb store error, code=%{public}d", errCode);
64         return errCode;
65     }
66     errCode = Attach("audit_event_attach", FOLDER_PATH + "audit_event.db", {});
67     if (errCode != NativeRdb::E_OK) {
68         SGLOGE("attach audit_event error, code=%{public}d", errCode);
69         return errCode;
70     }
71 
72     timer_.Setup();
73     timerId_ = timer_.Register([this] { this->FlushAllEvent(); }, FLUSH_INTERVAL);
74     return errCode;
75 }
76 
Release()77 void AuditEventMemRdbHelper::Release()
78 {
79     if (timerId_ != 0) {
80         timer_.Unregister(timerId_);
81     }
82     timer_.Shutdown();
83     (void)FlushAllEvent();
84 }
85 
QueryAllEvent(std::vector<SecEvent> & events)86 int AuditEventMemRdbHelper::QueryAllEvent(std::vector<SecEvent> &events)
87 {
88     NativeRdb::RdbPredicates predicates(AUDIT_TABLE);
89     int ret = QueryEventBase(predicates, events);
90     if (ret != NativeRdb::E_OK) {
91         SGLOGI("failed to query event, table=%{public}s, ret=%{public}d", AUDIT_TABLE, ret);
92         return DB_OPT_ERR;
93     }
94 
95     NativeRdb::RdbPredicates predicates2(dbTable_);
96     ret = QueryEventBase(predicates, events);
97     if (ret != NativeRdb::E_OK) {
98         SGLOGI("failed to query event, table=%{public}s, ret=%{public}d", dbTable_.c_str(), ret);
99         return DB_OPT_ERR;
100     }
101     return SUCCESS;
102 }
103 
QueryAllEventFromMem(std::vector<SecEvent> & events)104 int AuditEventMemRdbHelper::QueryAllEventFromMem(std::vector<SecEvent> &events)
105 {
106     return DatabaseHelper::QueryAllEvent(events);
107 }
108 
QueryEventFromMemByDate(std::vector<SecEvent> & events,std::string date)109 int AuditEventMemRdbHelper::QueryEventFromMemByDate(std::vector<SecEvent> &events, std::string date)
110 {
111     NativeRdb::RdbPredicates predicates(dbTable_);
112     predicates.LessThan(DATE, date);
113     std::vector<std::string> columns { EVENT_ID, VERSION, DATE, CONTENT, USER_ID, DEVICE_ID };
114     std::shared_ptr<NativeRdb::ResultSet> resultSet = Query(predicates, columns);
115     if (resultSet == nullptr) {
116         SGLOGI("failed to get event");
117         return DB_OPT_ERR;
118     }
119     SecEventTableInfo table;
120     int32_t ret = GetResultSetTableInfo(resultSet, table);
121     if (ret != SUCCESS) {
122         return ret;
123     }
124     while (resultSet->GoToNextRow() == NativeRdb::E_OK) {
125         SecEvent event;
126         resultSet->GetLong(table.eventIdIndex, event.eventId);
127         resultSet->GetString(table.versionIndex, event.version);
128         resultSet->GetString(table.dateIndex, event.date);
129         resultSet->GetString(table.contentIndex, event.content);
130         resultSet->GetInt(table.userIdIndex, event.userId);
131         resultSet->GetString(table.deviceIdIndex, event.deviceId);
132         events.emplace_back(event);
133     }
134     resultSet->Close();
135     return SUCCESS;
136 }
137 
DeleteRedundantData(const std::unordered_map<int64_t,int64_t> & countMap)138 void AuditEventMemRdbHelper::DeleteRedundantData(const std::unordered_map<int64_t, int64_t> &countMap)
139 {
140     for (const auto &entry : countMap) {
141         EventCfg config;
142         (void) ConfigDataManager::GetInstance().GetEventConfig(entry.first, config);
143         int64_t count = AuditEventRdbHelper::GetInstance().CountEventByEventId(entry.first);
144         if (count + entry.second >= config.storageRomNums) {
145             (void) AuditEventRdbHelper::GetInstance().DeleteOldEventByEventId(entry.first,
146                 count + entry.second - config.storageRomNums);
147         }
148     }
149 }
150 
DeleteFlushDataFromMem(std::string date)151 int AuditEventMemRdbHelper::DeleteFlushDataFromMem(std::string date)
152 {
153     NativeRdb::RdbPredicates predicates(dbTable_);
154     predicates.LessThan(DATE, date);
155     int32_t deleteRows;
156     int ret = Delete(deleteRows, predicates);
157     if (ret != NativeRdb::E_OK) {
158         SGLOGI("failed to delete event, ret=%{public}d", ret);
159     }
160     return ret;
161 }
162 
DeleteExpiredDataFromMain(std::string date)163 int AuditEventMemRdbHelper::DeleteExpiredDataFromMain(std::string date)
164 {
165     NativeRdb::RdbPredicates predicateDel(AUDIT_TABLE);
166     int64_t time;
167     SecurityGuardUtils::StrToI64(date, time);
168     time -= DELETE_INTERVAL;
169     predicateDel.LessThan(DATE, std::to_string(time));
170     int32_t deleteRows;
171     int ret = Delete(deleteRows, predicateDel);
172     if (ret != NativeRdb::E_OK) {
173         SGLOGI("failed to delete event, ret=%{public}d", ret);
174     }
175     return ret;
176 }
177 
FlushAllEvent()178 int AuditEventMemRdbHelper::FlushAllEvent()
179 {
180     SGLOGD("begin flush event from mem to file");
181     std::vector<SecEvent> events;
182     std::string date = SecurityGuardUtils::GetDate();
183     int ret = QueryEventFromMemByDate(events, date);
184     if (ret != NativeRdb::E_OK) {
185         SGLOGI("failed to query event, ret=%{public}d", ret);
186         return DB_OPT_ERR;
187     }
188     std::vector<NativeRdb::ValuesBucket> values;
189     std::unordered_map<int64_t, int64_t> countMap;
190     SGLOGD("flush event size is %{public}d", static_cast<int>(events.size()));
191     for (const SecEvent &event : events) {
192         countMap[event.eventId]++;
193         NativeRdb::ValuesBucket value;
194         SetValuesBucket(event, value);
195         values.emplace_back(value);
196     }
197 
198     DeleteRedundantData(countMap);
199     countMap.clear();
200 
201     int64_t rowId;
202     ret = BatchInsert(rowId, AUDIT_TABLE, values);
203     if (ret != NativeRdb::E_OK) {
204         SGLOGE("failed to batch insert event, ret=%{public}d", ret);
205         return DB_OPT_ERR;
206     }
207 
208     ret = DeleteFlushDataFromMem(date);
209     if (ret != NativeRdb::E_OK) {
210         SGLOGE("failed to delete flush event, ret=%{public}d", ret);
211         return DB_OPT_ERR;
212     }
213 
214     ret = DeleteExpiredDataFromMain(date);
215     if (ret != NativeRdb::E_OK) {
216         SGLOGE("failed to delete expired event, ret=%{public}d", ret);
217         return DB_OPT_ERR;
218     }
219     return SUCCESS;
220 }
221 } // namespace OHOS::Security::SecurityGuard