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 "database_helper.h"
17 #include <sstream>
18 #include <array>
19 #include <cinttypes>
20 #include "i_model_info.h"
21 #include "security_guard_define.h"
22 #include "security_guard_log.h"
23
24 namespace OHOS::Security::SecurityGuard {
DatabaseHelper(std::string dbTable)25 DatabaseHelper::DatabaseHelper(std::string dbTable)
26 {
27 dbTable_ = dbTable;
28 }
29
Init()30 int DatabaseHelper::Init()
31 {
32 return SUCCESS;
33 }
34
Release()35 void DatabaseHelper::Release()
36 {
37 }
38
InsertEvent(const SecEvent & event)39 int DatabaseHelper::InsertEvent(const SecEvent& event)
40 {
41 GenericValues values;
42 SetValuesBucket(event, values);
43 int64_t rowId;
44 int ret = Insert(rowId, dbTable_, values);
45 if (ret != SUCCESS) {
46 SGLOGI("failed to add event, eventId=%{public}" PRId64 ", ret=%{public}d", event.eventId, ret);
47 return FAILED;
48 }
49 return SUCCESS;
50 }
51
QueryAllEvent(std::vector<SecEvent> & events)52 int DatabaseHelper::QueryAllEvent(std::vector<SecEvent> &events)
53 {
54 return QueryEventBase({}, events, {});
55 }
56
QueryRecentEventByEventId(int64_t eventId,SecEvent & event)57 int DatabaseHelper::QueryRecentEventByEventId(int64_t eventId, SecEvent &event)
58 {
59 std::vector<SecEvent> results;
60 QueryOptions options;
61 options.orderBy = std::string(ID) + " DESC";
62 options.limit = 1;
63 GenericValues conditions;
64 conditions.Put(EVENT_ID, std::to_string(eventId));
65 int ret = QueryEventBase(conditions, results, options);
66 if (ret == SUCCESS && !results.empty()) {
67 event = results[0];
68 return SUCCESS;
69 }
70 return FAILED;
71 }
72
QueryRecentEventByEventId(const std::vector<int64_t> & eventIds,std::vector<SecEvent> & events)73 int DatabaseHelper::QueryRecentEventByEventId(const std::vector<int64_t> &eventIds, std::vector<SecEvent> &events)
74 {
75 if (eventIds.empty()) {
76 return FAILED;
77 }
78
79 std::vector<std::string> idStrList;
80 for (const auto &id: eventIds) {
81 idStrList.push_back(std::to_string(id));
82 }
83
84 GenericValues conditions;
85 conditions.Put(std::string(EVENT_ID) + "_IN", Join(idStrList, ","));
86
87 QueryOptions options;
88 options.orderBy = std::string(DATE) + " DESC";
89 options.limit = 1;
90 int ret = QueryEventBase(conditions, events, options);
91 if (ret != SUCCESS) {
92 SGLOGE("query fail");
93 events.clear();
94 }
95 return ret;
96 }
97
QueryEventByEventId(int64_t eventId,std::vector<SecEvent> & events)98 int DatabaseHelper::QueryEventByEventId(int64_t eventId, std::vector<SecEvent> &events)
99 {
100 GenericValues conditions;
101 conditions.Put(EVENT_ID, std::to_string(eventId));
102 return QueryEventBase(conditions, events);
103 }
104
QueryEventByEventId(std::vector<int64_t> & eventIds,std::vector<SecEvent> & events)105 int DatabaseHelper::QueryEventByEventId(std::vector<int64_t> &eventIds, std::vector<SecEvent> &events)
106 {
107 if (eventIds.empty()) {
108 return BAD_PARAM;
109 }
110
111 std::ostringstream oss;
112 for (size_t i = 0; i < eventIds.size(); ++i) {
113 if (i > 0) {
114 oss << ",";
115 }
116 oss << eventIds[i];
117 }
118
119 GenericValues conditions;
120 conditions.Put(std::string(EVENT_ID) + "_IN", oss.str());
121 return QueryEventBase(conditions, events);
122 }
123
QueryEventByEventIdAndDate(std::vector<int64_t> & eventIds,std::vector<SecEvent> & events,std::string beginTime,std::string endTime)124 int DatabaseHelper::QueryEventByEventIdAndDate(std::vector<int64_t> &eventIds, std::vector<SecEvent> &events,
125 std::string beginTime, std::string endTime)
126 {
127 if (eventIds.empty()) {
128 return BAD_PARAM;
129 }
130
131 GenericValues conditions;
132 conditions.Put(std::string(EVENT_ID) + "_IN", Join(eventIds, ","));
133 if (!beginTime.empty()) {
134 conditions.Put(std::string(DATE) + "_GE", beginTime);
135 }
136
137 if (!endTime.empty()) {
138 conditions.Put(std::string(DATE) + "_LT", endTime);
139 }
140 return QueryEventBase(conditions, events);
141 }
142
QueryEventByEventType(int32_t eventType,std::vector<SecEvent> & events)143 int DatabaseHelper::QueryEventByEventType(int32_t eventType, std::vector<SecEvent> &events)
144 {
145 GenericValues conditions;
146 conditions.Put(EVENT_TYPE, std::to_string(eventType));
147 return QueryEventBase(conditions, events);
148 }
149
QueryEventByLevel(int32_t level,std::vector<SecEvent> & events)150 int DatabaseHelper::QueryEventByLevel(int32_t level, std::vector<SecEvent> &events)
151 {
152 GenericValues conditions;
153 conditions.Put(DATA_SENSITIVITY_LEVEL, std::to_string(level));
154 return QueryEventBase(conditions, events);
155 }
156
QueryEventByOwner(std::string owner,std::vector<SecEvent> & events)157 int DatabaseHelper::QueryEventByOwner(std::string owner, std::vector<SecEvent> &events)
158 {
159 GenericValues conditions;
160 std::string safeOwner = FilterSpecialChars(owner);
161 conditions.Put(std::string(OWNER) + "_LIKE", "%" + safeOwner + "%");
162 return QueryEventBase(conditions, events);
163 }
164
CountAllEvent()165 int64_t DatabaseHelper::CountAllEvent()
166 {
167 int64_t count;
168 int ret = Count(count, dbTable_, {});
169 if (ret != SUCCESS) {
170 SGLOGE("failed to count event, ret=%{public}d", ret);
171 }
172 return count;
173 }
174
CountEventByEventId(int64_t eventId)175 int64_t DatabaseHelper::CountEventByEventId(int64_t eventId)
176 {
177 int64_t count;
178 GenericValues conditions;
179 conditions.Put(EVENT_ID, std::to_string(eventId));
180 int ret = Count(count, dbTable_, conditions);
181 if (ret != SUCCESS) {
182 SGLOGE("failed to count event, eventId=%{public}" PRId64 ", ret=%{public}d", eventId, ret);
183 }
184 return count;
185 }
186
DeleteOldEventByEventId(int64_t eventId,int64_t count)187 int DatabaseHelper::DeleteOldEventByEventId(int64_t eventId, int64_t count)
188 {
189 if (count <= 0 || eventId < 0) {
190 return BAD_PARAM;
191 }
192 GenericValues conditions;
193 conditions.Put(EVENT_ID, std::to_string(eventId));
194 QueryOptions options;
195 options.orderBy = std::string(DATE) + " ASC";
196 options.limit = static_cast<int>(count);
197 options.columns = {ID};
198
199 std::vector<GenericValues> idResults;
200 int ret = Query(dbTable_, conditions, idResults, options);
201 if (ret != SUCCESS || idResults.empty()) {
202 return ret;
203 }
204
205 std::vector<std::string> primaryKeys;
206 for (const auto& row: idResults) {
207 primaryKeys.push_back(std::to_string(row.GetInt64(ID)));
208 }
209
210 GenericValues deleteConditions;
211 deleteConditions.Put(std::string(ID) + "_IN", Join(primaryKeys, ","));
212 int deleteRows = 0;
213 return Delete(deleteRows, dbTable_, deleteConditions);
214 }
215
DeleteAllEventByEventId(int64_t eventId)216 int DatabaseHelper::DeleteAllEventByEventId(int64_t eventId)
217 {
218 if (eventId < 0) {
219 return BAD_PARAM;
220 }
221 GenericValues conditions;
222 conditions.Put(EVENT_ID, std::to_string(eventId));
223 int deleteRows = 0;
224 return Delete(deleteRows, dbTable_, conditions);
225 }
226
FlushAllEvent()227 int DatabaseHelper::FlushAllEvent()
228 {
229 return SUCCESS;
230 }
231
QueryEventBase(const GenericValues & conditions,std::vector<SecEvent> & events,const QueryOptions & options)232 int DatabaseHelper::QueryEventBase(const GenericValues &conditions, std::vector<SecEvent> &events,
233 const QueryOptions &options)
234 {
235 std::vector<GenericValues> queryResults;
236 QueryOptions baseOptions = options;
237 baseOptions.columns = {EVENT_ID, VERSION, DATE, CONTENT, USER_ID, DEVICE_ID};
238
239 int ret = Query(dbTable_, conditions, queryResults, baseOptions);
240 if (ret != SUCCESS) {
241 return ret;
242 }
243
244 for (const auto& row : queryResults) {
245 events.emplace_back(
246 SecEvent{
247 .eventId = row.GetInt64(EVENT_ID),
248 .date = row.GetString(DATE),
249 .content = row.GetString(CONTENT),
250 .userId = row.GetInt(USER_ID),
251 .deviceId = row.GetString(DEVICE_ID)
252 }
253 );
254 }
255
256 return SUCCESS;
257 }
258
SetValuesBucket(const SecEvent & event,GenericValues & values)259 void DatabaseHelper::SetValuesBucket(const SecEvent &event, GenericValues &values)
260 {
261 values.Put(EVENT_ID, event.eventId);
262 values.Put(VERSION, event.version);
263 values.Put(DATE, event.date);
264 values.Put(CONTENT, event.content);
265 values.Put(EVENT_TYPE, event.eventType);
266 values.Put(DATA_SENSITIVITY_LEVEL, event.dataSensitivityLevel);
267 values.Put(OWNER, event.owner);
268 values.Put(USER_ID, event.userId);
269 values.Put(DEVICE_ID, event.deviceId);
270 }
271
CreateTable()272 std::string DatabaseHelper::CreateTable()
273 {
274 std::string table;
275 table.append("CREATE TABLE IF NOT EXISTS ").append(dbTable_);
276 table.append("(").append(ID).append(" INTEGER PRIMARY KEY AUTOINCREMENT, ");
277 table.append(EVENT_ID).append(" INTEGER NOT NULL, ");
278 table.append(VERSION).append(" TEXT NOT NULL, ");
279 table.append(DATE).append(" TEXT NOT NULL, ");
280 table.append(CONTENT).append(" TEXT NOT NULL, ");
281 table.append(EVENT_TYPE).append(" INTEGER NOT NULL, ");
282 table.append(DATA_SENSITIVITY_LEVEL).append(" INTEGER NOT NULL, ");
283 table.append(OWNER).append(" TEXT NOT NULL, ");
284 table.append(USER_ID).append(" INTEGER NOT NULL, ");
285 table.append(DEVICE_ID).append(" TEXT NOT NULL)");
286 return table;
287 }
288
FilterSpecialChars(const std::string & input)289 std::string DatabaseHelper::FilterSpecialChars(const std::string &input)
290 {
291 std::string filtered;
292 for (auto c : input) {
293 if (isalnum(c) || c == '_' || c == '%') {
294 filtered += c;
295 }
296 }
297
298 return filtered;
299 }
300
Join(const std::vector<int64_t> & vec,const std::string delimiter)301 std::string DatabaseHelper::Join(const std::vector<int64_t> &vec, const std::string delimiter)
302 {
303 if (vec.empty()) {
304 return "";
305 }
306
307 std::ostringstream oss;
308 oss << vec[0];
309
310 for (size_t i = 1; i < vec.size(); ++i) {
311 oss << delimiter << vec[i];
312 }
313
314 return oss.str();
315 }
316
Join(const std::vector<std::string> & vec,const std::string delimiter)317 std::string DatabaseHelper::Join(const std::vector<std::string> &vec, const std::string delimiter)
318 {
319 if (vec.empty()) {
320 return "";
321 }
322
323 std::string result;
324 bool isFirst = true;
325 for (const auto &str : vec) {
326 if (!isFirst) {
327 result += delimiter;
328 }
329 result += str;
330 isFirst = false;
331 }
332
333 return result;
334 }
335
336 } // namespace OHOS::Security::SecurityGuard