1 /*
2 * Copyright (c) 2022 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 "permission_used_record_db.h"
17
18 #include "accesstoken_log.h"
19 #include "constant.h"
20 #include "privacy_field_const.h"
21 #include "active_change_response_info.h"
22
23 namespace OHOS {
24 namespace Security {
25 namespace AccessToken {
26 namespace {
27 static constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {
28 LOG_CORE, SECURITY_DOMAIN_PRIVACY, "PermissionUsedRecordDb"
29 };
30 static const std::string FIELD_COUNT_NUMBER = "count";
31 static const std::string INTEGER_STR = " integer not null,";
32 }
33
GetInstance()34 PermissionUsedRecordDb& PermissionUsedRecordDb::GetInstance()
35 {
36 static PermissionUsedRecordDb instance;
37 return instance;
38 }
39
~PermissionUsedRecordDb()40 PermissionUsedRecordDb::~PermissionUsedRecordDb()
41 {
42 Close();
43 }
44
OnCreate()45 void PermissionUsedRecordDb::OnCreate()
46 {
47 ACCESSTOKEN_LOG_INFO(LABEL, "Entry");
48 CreatePermissionRecordTable();
49 }
50
OnUpdate()51 void PermissionUsedRecordDb::OnUpdate()
52 {
53 ACCESSTOKEN_LOG_INFO(LABEL, "Entry");
54 InsertLockScreenStatusColumn();
55 }
56
PermissionUsedRecordDb()57 PermissionUsedRecordDb::PermissionUsedRecordDb() : SqliteHelper(DATABASE_NAME, DATABASE_PATH, DATABASE_VERSION)
58 {
59 SqliteTable permissionRecordTable;
60 permissionRecordTable.tableName_ = PERMISSION_RECORD_TABLE;
61 permissionRecordTable.tableColumnNames_ = {
62 PrivacyFiledConst::FIELD_TOKEN_ID,
63 PrivacyFiledConst::FIELD_OP_CODE,
64 PrivacyFiledConst::FIELD_STATUS,
65 PrivacyFiledConst::FIELD_TIMESTAMP,
66 PrivacyFiledConst::FIELD_ACCESS_DURATION,
67 PrivacyFiledConst::FIELD_ACCESS_COUNT,
68 PrivacyFiledConst::FIELD_REJECT_COUNT,
69 PrivacyFiledConst::FIELD_LOCKSCREEN_STATUS
70 };
71
72 dataTypeToSqlTable_ = {
73 {PERMISSION_RECORD, permissionRecordTable},
74 };
75 Open();
76 }
77
Add(DataType type,const std::vector<GenericValues> & values)78 int32_t PermissionUsedRecordDb::Add(DataType type, const std::vector<GenericValues>& values)
79 {
80 OHOS::Utils::UniqueWriteGuard<OHOS::Utils::RWLock> lock(this->rwLock_);
81 std::string prepareSql = CreateInsertPrepareSqlCmd(type);
82 auto statement = Prepare(prepareSql);
83 BeginTransaction();
84 bool isAddSuccessfully = true;
85 for (const auto& value : values) {
86 std::vector<std::string> columnNames = value.GetAllKeys();
87 for (const auto& name : columnNames) {
88 statement.Bind(name, value.Get(name));
89 }
90 int32_t ret = statement.Step();
91 if (ret != Statement::State::DONE) {
92 ACCESSTOKEN_LOG_ERROR(LABEL, "failed, errorMsg: %{public}s", SpitError().c_str());
93 isAddSuccessfully = false;
94 }
95 statement.Reset();
96 }
97 if (!isAddSuccessfully) {
98 ACCESSTOKEN_LOG_ERROR(LABEL, "rollback transaction.");
99 RollbackTransaction();
100 return FAILURE;
101 }
102 ACCESSTOKEN_LOG_DEBUG(LABEL, "commit transaction.");
103 CommitTransaction();
104 return SUCCESS;
105 }
106
Remove(DataType type,const GenericValues & conditions)107 int32_t PermissionUsedRecordDb::Remove(DataType type, const GenericValues& conditions)
108 {
109 OHOS::Utils::UniqueWriteGuard<OHOS::Utils::RWLock> lock(this->rwLock_);
110 std::vector<std::string> columnNames = conditions.GetAllKeys();
111 std::string prepareSql = CreateDeletePrepareSqlCmd(type, columnNames);
112 auto statement = Prepare(prepareSql);
113 for (const auto& columnName : columnNames) {
114 statement.Bind(columnName, conditions.Get(columnName));
115 }
116 int32_t ret = statement.Step();
117 return (ret == Statement::State::DONE) ? SUCCESS : FAILURE;
118 }
119
FindByConditions(DataType type,const std::set<int32_t> & opCodeList,const GenericValues & andConditions,std::vector<GenericValues> & results,int32_t databaseQueryCount)120 int32_t PermissionUsedRecordDb::FindByConditions(DataType type, const std::set<int32_t>& opCodeList,
121 const GenericValues& andConditions, std::vector<GenericValues>& results, int32_t databaseQueryCount)
122 {
123 OHOS::Utils::UniqueWriteGuard<OHOS::Utils::RWLock> lock(this->rwLock_);
124 std::vector<std::string> andColumns = andConditions.GetAllKeys();
125 std::string prepareSql = CreateSelectByConditionPrepareSqlCmd(type, opCodeList, andColumns, databaseQueryCount);
126
127 auto statement = Prepare(prepareSql);
128
129 for (const auto& columnName : andColumns) {
130 statement.Bind(columnName, andConditions.Get(columnName));
131 }
132
133 while (statement.Step() == Statement::State::ROW) {
134 int32_t columnCount = statement.GetColumnCount();
135 GenericValues value;
136 for (int32_t i = 0; i < columnCount; i++) {
137 if ((statement.GetColumnName(i) == PrivacyFiledConst::FIELD_TIMESTAMP) ||
138 (statement.GetColumnName(i) == PrivacyFiledConst::FIELD_ACCESS_DURATION)) {
139 value.Put(statement.GetColumnName(i), statement.GetValue(i, true));
140 } else {
141 value.Put(statement.GetColumnName(i), statement.GetValue(i, false));
142 }
143 }
144 results.emplace_back(value);
145 }
146 return SUCCESS;
147 }
148
GetDistinctValue(DataType type,const std::string & condition,std::vector<GenericValues> & results)149 int32_t PermissionUsedRecordDb::GetDistinctValue(DataType type,
150 const std::string& condition, std::vector<GenericValues>& results)
151 {
152 OHOS::Utils::UniqueWriteGuard<OHOS::Utils::RWLock> lock(this->rwLock_);
153 std::string getDistinctValueSql = CreateGetDistinctValue(type, condition);
154 auto statement = Prepare(getDistinctValueSql);
155 while (statement.Step() == Statement::State::ROW) {
156 int32_t columnCount = statement.GetColumnCount();
157 GenericValues value;
158 for (int32_t i = 0; i < columnCount; i++) {
159 if (statement.GetColumnName(i) == PrivacyFiledConst::FIELD_TOKEN_ID) {
160 value.Put(statement.GetColumnName(i), statement.GetValue(i, false));
161 } else if (statement.GetColumnName(i) == PrivacyFiledConst::FIELD_DEVICE_ID) {
162 value.Put(statement.GetColumnName(i), statement.GetColumnString(i));
163 }
164 }
165 results.emplace_back(value);
166 }
167 return SUCCESS;
168 }
169
Count(DataType type,GenericValues & result)170 void PermissionUsedRecordDb::Count(DataType type, GenericValues& result)
171 {
172 OHOS::Utils::UniqueWriteGuard<OHOS::Utils::RWLock> lock(this->rwLock_);
173 std::string countSql = CreateCountPrepareSqlCmd(type);
174 auto countStatement = Prepare(countSql);
175 if (countStatement.Step() == Statement::State::ROW) {
176 int32_t column = 0;
177 result.Put(FIELD_COUNT_NUMBER, countStatement.GetValue(column, true));
178 }
179 }
180
DeleteExpireRecords(DataType type,const GenericValues & andConditions)181 int32_t PermissionUsedRecordDb::DeleteExpireRecords(DataType type,
182 const GenericValues& andConditions)
183 {
184 OHOS::Utils::UniqueWriteGuard<OHOS::Utils::RWLock> lock(this->rwLock_);
185 std::vector<std::string> andColumns = andConditions.GetAllKeys();
186 if (!andColumns.empty()) {
187 std::string deleteExpireSql = CreateDeleteExpireRecordsPrepareSqlCmd(type, andColumns);
188 auto deleteExpireStatement = Prepare(deleteExpireSql);
189 for (const auto& columnName : andColumns) {
190 deleteExpireStatement.Bind(columnName, andConditions.Get(columnName));
191 }
192 if (deleteExpireStatement.Step() != Statement::State::DONE) {
193 return FAILURE;
194 }
195 }
196 return SUCCESS;
197 }
198
DeleteExcessiveRecords(DataType type,uint32_t excessiveSize)199 int32_t PermissionUsedRecordDb::DeleteExcessiveRecords(DataType type, uint32_t excessiveSize)
200 {
201 OHOS::Utils::UniqueWriteGuard<OHOS::Utils::RWLock> lock(this->rwLock_);
202 std::string deleteExcessiveSql = CreateDeleteExcessiveRecordsPrepareSqlCmd(type, excessiveSize);
203 auto deleteExcessiveStatement = Prepare(deleteExcessiveSql);
204 if (deleteExcessiveStatement.Step() != Statement::State::DONE) {
205 return FAILURE;
206 }
207 return SUCCESS;
208 }
209
CreateInsertPrepareSqlCmd(DataType type) const210 std::string PermissionUsedRecordDb::CreateInsertPrepareSqlCmd(DataType type) const
211 {
212 auto it = dataTypeToSqlTable_.find(type);
213 if (it == dataTypeToSqlTable_.end()) {
214 return std::string();
215 }
216 std::string sql = "insert into " + it->second.tableName_ + " values(";
217 int32_t i = 1;
218 for (const auto& name : it->second.tableColumnNames_) {
219 sql.append(":" + name);
220 if (i < static_cast<int32_t>(it->second.tableColumnNames_.size())) {
221 sql.append(",");
222 }
223 i += 1;
224 }
225 sql.append(")");
226 return sql;
227 }
228
CreateDeletePrepareSqlCmd(DataType type,const std::vector<std::string> & columnNames) const229 std::string PermissionUsedRecordDb::CreateDeletePrepareSqlCmd(
230 DataType type, const std::vector<std::string>& columnNames) const
231 {
232 auto it = dataTypeToSqlTable_.find(type);
233 if (it == dataTypeToSqlTable_.end()) {
234 return std::string();
235 }
236 std::string sql = "delete from " + it->second.tableName_ + " where 1 = 1";
237 for (const auto& name : columnNames) {
238 sql.append(" and ");
239 sql.append(name + "=:" + name);
240 }
241 return sql;
242 }
243
CreateUpdatePrepareSqlCmd(DataType type,const std::vector<std::string> & modifyColumns,const std::vector<std::string> & conditionColumns) const244 std::string PermissionUsedRecordDb::CreateUpdatePrepareSqlCmd(DataType type,
245 const std::vector<std::string>& modifyColumns, const std::vector<std::string>& conditionColumns) const
246 {
247 if (modifyColumns.empty()) {
248 return std::string();
249 }
250
251 auto it = dataTypeToSqlTable_.find(type);
252 if (it == dataTypeToSqlTable_.end()) {
253 return std::string();
254 }
255
256 std::string sql = "update " + it->second.tableName_ + " set ";
257 int32_t i = 1;
258 for (const auto& name : modifyColumns) {
259 sql.append(name + "=:" + name);
260 if (i < static_cast<int32_t>(modifyColumns.size())) {
261 sql.append(",");
262 }
263 i += 1;
264 }
265
266 if (!conditionColumns.empty()) {
267 sql.append(" where 1 = 1");
268 for (const auto& columnName : conditionColumns) {
269 sql.append(" and ");
270 sql.append(columnName + "=:" + columnName);
271 }
272 }
273 return sql;
274 }
275
CreateSelectByConditionPrepareSqlCmd(DataType type,const std::set<int32_t> & opCodeList,const std::vector<std::string> & andColumns,int32_t databaseQueryCount) const276 std::string PermissionUsedRecordDb::CreateSelectByConditionPrepareSqlCmd(DataType type,
277 const std::set<int32_t>& opCodeList, const std::vector<std::string>& andColumns, int32_t databaseQueryCount) const
278 {
279 auto it = dataTypeToSqlTable_.find(type);
280 if (it == dataTypeToSqlTable_.end()) {
281 return std::string();
282 }
283
284 std::string sql = "select * from " + it->second.tableName_ + " where 1 = 1";
285
286 for (const auto& andColName : andColumns) {
287 if (andColName == PrivacyFiledConst::FIELD_TIMESTAMP_BEGIN) {
288 sql.append(" and ");
289 sql.append(PrivacyFiledConst::FIELD_TIMESTAMP);
290 sql.append(" >=:" + andColName);
291 } else if (andColName == PrivacyFiledConst::FIELD_TIMESTAMP_END) {
292 sql.append(" and ");
293 sql.append(PrivacyFiledConst::FIELD_TIMESTAMP);
294 sql.append(" <=:" + andColName);
295 } else {
296 sql.append(" and ");
297 sql.append(andColName + "=:" + andColName);
298 }
299 }
300 if (!opCodeList.empty()) {
301 sql.append(" and (");
302 for (const auto& opCode : opCodeList) {
303 if (opCode != Constant::OP_INVALID) {
304 sql.append(PrivacyFiledConst::FIELD_OP_CODE);
305 sql.append(+ " = " + std::to_string(opCode));
306 sql.append(" or ");
307 }
308 }
309 sql.append("0)");
310 }
311 sql.append(" limit " + std::to_string(databaseQueryCount));
312 return sql;
313 }
314
CreateCountPrepareSqlCmd(DataType type) const315 std::string PermissionUsedRecordDb::CreateCountPrepareSqlCmd(DataType type) const
316 {
317 auto it = dataTypeToSqlTable_.find(type);
318 if (it == dataTypeToSqlTable_.end()) {
319 return std::string();
320 }
321 std::string sql = "select count(*) from " + it->second.tableName_;
322 return sql;
323 }
324
CreateDeleteExpireRecordsPrepareSqlCmd(DataType type,const std::vector<std::string> & andColumns) const325 std::string PermissionUsedRecordDb::CreateDeleteExpireRecordsPrepareSqlCmd(DataType type,
326 const std::vector<std::string>& andColumns) const
327 {
328 auto it = dataTypeToSqlTable_.find(type);
329 if (it == dataTypeToSqlTable_.end()) {
330 return std::string();
331 }
332 std::string sql = "delete from " + it->second.tableName_ + " where ";
333 sql.append(PrivacyFiledConst::FIELD_TIMESTAMP);
334 sql.append(" in (select ");
335 sql.append(PrivacyFiledConst::FIELD_TIMESTAMP);
336 sql.append(" from " + it->second.tableName_ + " where 1 = 1");
337 for (const auto& name : andColumns) {
338 if (name == PrivacyFiledConst::FIELD_TIMESTAMP_BEGIN) {
339 sql.append(" and ");
340 sql.append(PrivacyFiledConst::FIELD_TIMESTAMP);
341 sql.append(" >=:" + name);
342 } else if (name == PrivacyFiledConst::FIELD_TIMESTAMP_END) {
343 sql.append(" and ");
344 sql.append(PrivacyFiledConst::FIELD_TIMESTAMP);
345 sql.append(" <=:" + name);
346 } else {
347 sql.append(" and ");
348 sql.append(name + "=:" + name);
349 }
350 }
351 sql.append(" )");
352 return sql;
353 }
354
CreateDeleteExcessiveRecordsPrepareSqlCmd(DataType type,uint32_t excessiveSize) const355 std::string PermissionUsedRecordDb::CreateDeleteExcessiveRecordsPrepareSqlCmd(DataType type,
356 uint32_t excessiveSize) const
357 {
358 auto it = dataTypeToSqlTable_.find(type);
359 if (it == dataTypeToSqlTable_.end()) {
360 return std::string();
361 }
362 std::string sql = "delete from " + it->second.tableName_ + " where ";
363 sql.append(PrivacyFiledConst::FIELD_TIMESTAMP);
364 sql.append(" in (select ");
365 sql.append(PrivacyFiledConst::FIELD_TIMESTAMP);
366 sql.append(" from " + it->second.tableName_ + " order by ");
367 sql.append(PrivacyFiledConst::FIELD_TIMESTAMP);
368 sql.append(" limit ");
369 sql.append(std::to_string(excessiveSize) + " )");
370 return sql;
371 }
372
CreateGetDistinctValue(DataType type,const std::string conditionColumns) const373 std::string PermissionUsedRecordDb::CreateGetDistinctValue(DataType type,
374 const std::string conditionColumns) const
375 {
376 auto it = dataTypeToSqlTable_.find(type);
377 if (it == dataTypeToSqlTable_.end()) {
378 return std::string();
379 }
380 std::string sql = "select distinct ";
381 sql.append(conditionColumns + " from "+ it->second.tableName_);
382 return sql;
383 }
384
CreatePermissionRecordTable() const385 int32_t PermissionUsedRecordDb::CreatePermissionRecordTable() const
386 {
387 auto it = dataTypeToSqlTable_.find(DataType::PERMISSION_RECORD);
388 if (it == dataTypeToSqlTable_.end()) {
389 return FAILURE;
390 }
391 std::string sql = "create table if not exists ";
392 sql.append(it->second.tableName_ + " (")
393 .append(PrivacyFiledConst::FIELD_TOKEN_ID)
394 .append(" integer not null,")
395 .append(PrivacyFiledConst::FIELD_OP_CODE)
396 .append(" integer not null,")
397 .append(PrivacyFiledConst::FIELD_STATUS)
398 .append(" integer not null,")
399 .append(PrivacyFiledConst::FIELD_TIMESTAMP)
400 .append(" integer not null,")
401 .append(PrivacyFiledConst::FIELD_ACCESS_DURATION)
402 .append(" integer not null,")
403 .append(PrivacyFiledConst::FIELD_ACCESS_COUNT)
404 .append(" integer not null,")
405 .append(PrivacyFiledConst::FIELD_REJECT_COUNT)
406 .append(" integer not null,")
407 .append(PrivacyFiledConst::FIELD_LOCKSCREEN_STATUS)
408 .append(" integer not null,")
409 .append("primary key(")
410 .append(PrivacyFiledConst::FIELD_TOKEN_ID)
411 .append(",")
412 .append(PrivacyFiledConst::FIELD_OP_CODE)
413 .append(",")
414 .append(PrivacyFiledConst::FIELD_STATUS)
415 .append(",")
416 .append(PrivacyFiledConst::FIELD_TIMESTAMP)
417 .append("))");
418 return ExecuteSql(sql);
419 }
420
InsertLockScreenStatusColumn() const421 int32_t PermissionUsedRecordDb::InsertLockScreenStatusColumn() const
422 {
423 ACCESSTOKEN_LOG_INFO(LABEL, "Entry");
424 auto it = dataTypeToSqlTable_.find(DataType::PERMISSION_RECORD);
425 if (it == dataTypeToSqlTable_.end()) {
426 return FAILURE;
427 }
428 std::string checkSql = "SELECT 1 FROM " + it->second.tableName_ + " WHERE " +
429 PrivacyFiledConst::FIELD_LOCKSCREEN_STATUS + "=" +
430 std::to_string(LockScreenStatusChangeType::PERM_ACTIVE_IN_UNLOCKED);
431 int32_t checkResult = ExecuteSql(checkSql);
432 ACCESSTOKEN_LOG_INFO(LABEL, "check result:%{public}d", checkResult);
433 if (checkResult != -1) {
434 return SUCCESS;
435 }
436
437 std::string sql = "alter table ";
438 sql.append(it->second.tableName_ + " add column ")
439 .append(PrivacyFiledConst::FIELD_LOCKSCREEN_STATUS)
440 .append(" integer default ")
441 .append(std::to_string(LockScreenStatusChangeType::PERM_ACTIVE_IN_UNLOCKED));
442 int32_t insertResult = ExecuteSql(sql);
443 ACCESSTOKEN_LOG_INFO(LABEL, "insert column result:%{public}d", insertResult);
444 return insertResult;
445 }
446 } // namespace AccessToken
447 } // namespace Security
448 } // namespace OHOS
449