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