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 "config_database_helper.h"
17 #include <vector>
18 #include <array>
19 #include "string_ex.h"
20 #include "config_define.h"
21 #include "rdb_event_store_callback.h"
22 #include "security_guard_define.h"
23 #include "security_guard_log.h"
24
25 namespace OHOS::Security::SecurityGuard {
ConfigDatabaseHelper(std::string dbTable)26 ConfigDatabaseHelper::ConfigDatabaseHelper(std::string dbTable)
27 {
28 dbTable_ = dbTable;
29 }
30
Init()31 int ConfigDatabaseHelper::Init()
32 {
33 return SUCCESS;
34 }
35
InsertAppInfo(const AppInfo & info)36 int ConfigDatabaseHelper::InsertAppInfo(const AppInfo& info)
37 {
38 NativeRdb::ValuesBucket values {};
39 SetValuesBucket(info, values);
40 int64_t rowId;
41 int ret = Insert(rowId, dbTable_, values);
42 if (ret != NativeRdb::E_OK) {
43 SGLOGI("failed to add app info, appName=%{public}s, ret=%{public}d", info.appName.c_str(), ret);
44 return DB_OPT_ERR;
45 }
46 return SUCCESS;
47 }
48
InsertAllAppInfo(const std::vector<AppInfo> & infos)49 int ConfigDatabaseHelper::InsertAllAppInfo(const std::vector<AppInfo>& infos)
50 {
51 SGLOGI("InsertAllAppInfo....");
52 std::vector<NativeRdb::ValuesBucket> values {};
53 for (auto iter : infos) {
54 NativeRdb::ValuesBucket value {};
55 SetValuesBucket(iter, value);
56 values.emplace_back(value);
57 }
58 int64_t rowId;
59 int ret = BatchInsert(rowId, dbTable_, values);
60 if (ret != NativeRdb::E_OK) {
61 SGLOGE("failed to batch insert event, ret=%{public}d", ret);
62 return DB_OPT_ERR;
63 }
64 return SUCCESS;
65 }
66
QueryAllAppInfo(std::vector<AppInfo> & infos)67 int ConfigDatabaseHelper::QueryAllAppInfo(std::vector<AppInfo> &infos)
68 {
69 SGLOGI("QueryAllAppInfo....");
70 NativeRdb::RdbPredicates predicates(dbTable_);
71 return QueryAppInfoBase(predicates, infos);
72 }
73
QueryAppInfoBase(const NativeRdb::RdbPredicates & predicates,std::vector<AppInfo> & infos)74 int32_t ConfigDatabaseHelper::QueryAppInfoBase(const NativeRdb::RdbPredicates &predicates, std::vector<AppInfo> &infos)
75 {
76 std::vector<std::string> columns {APP_NAME, APP_FINGERPRINT, APP_ATTRIBUTES, IS_GLOBAL_APP};
77 std::shared_ptr<NativeRdb::ResultSet> resultSet = Query(predicates, columns);
78 if (resultSet == nullptr) {
79 SGLOGE("failed to get event");
80 return DB_OPT_ERR;
81 }
82 AppInfoTableInfo table;
83 int32_t ret = GetResultSetTableInfo(resultSet, table);
84 if (ret != SUCCESS) {
85 return ret;
86 }
87 while (resultSet->GoToNextRow() == NativeRdb::E_OK) {
88 AppInfo info;
89 resultSet->GetString(table.appNameIndex, info.appName);
90 resultSet->GetString(table.appHashIndex, info.appHash);
91 std::string attrStr;
92 std::vector<std::string> tmpVec;
93 resultSet->GetString(table.appAttrIndex, attrStr);
94 SplitStr(attrStr, ",", tmpVec);
95 info.attrs = tmpVec;
96 resultSet->GetInt(table.appIsGlobalAppIndex, info.isGlobalApp);
97 infos.emplace_back(info);
98 }
99 resultSet->Close();
100 return SUCCESS;
101 }
102
GetResultSetTableInfo(const std::shared_ptr<NativeRdb::ResultSet> & resultSet,AppInfoTableInfo & table)103 int32_t ConfigDatabaseHelper::GetResultSetTableInfo(const std::shared_ptr<NativeRdb::ResultSet> &resultSet,
104 AppInfoTableInfo &table)
105 {
106 int32_t rowCount = 0;
107 int32_t columnCount = 0;
108 std::vector<std::string> columnNames;
109 if (resultSet->GetRowCount(rowCount) != NativeRdb::E_OK ||
110 resultSet->GetColumnCount(columnCount) != NativeRdb::E_OK ||
111 resultSet->GetAllColumnNames(columnNames) != NativeRdb::E_OK) {
112 SGLOGE("get table info failed");
113 return DB_LOAD_ERR;
114 }
115 int32_t columnNamesCount = static_cast<int32_t>(columnNames.size());
116 for (int32_t i = 0; i < columnNamesCount; i++) {
117 std::string columnName = columnNames.at(i);
118 if (columnName == ID) {
119 table.primaryKeyIndex = i;
120 }
121 if (columnName == APP_NAME) {
122 table.appNameIndex = i;
123 }
124 if (columnName == APP_FINGERPRINT) {
125 table.appHashIndex = i;
126 }
127 if (columnName == APP_ATTRIBUTES) {
128 table.appAttrIndex = i;
129 }
130 if (columnName == IS_GLOBAL_APP) {
131 table.appIsGlobalAppIndex = i;
132 }
133 }
134 table.rowCount = rowCount;
135 table.columnCount = columnCount;
136 SGLOGD("info: row=%{public}d col=%{public}d appNameIdx=%{public}d appHashIdx=%{public}d "
137 "appAttrIdx=%{public}d", rowCount, columnCount,
138 table.appNameIndex, table.appHashIndex, table.appAttrIndex);
139 return SUCCESS;
140 }
141
QueryAppInfosByName(const std::string & appName,std::vector<AppInfo> & infos)142 int ConfigDatabaseHelper::QueryAppInfosByName(const std::string &appName, std::vector<AppInfo> &infos)
143 {
144 std::vector<std::string> columns {APP_NAME, APP_FINGERPRINT, APP_ATTRIBUTES, IS_GLOBAL_APP};
145 NativeRdb::RdbPredicates predicates(dbTable_);
146 predicates.EqualTo(APP_NAME, appName);
147 predicates.OrderByDesc(ID);
148 std::shared_ptr<NativeRdb::ResultSet> resultSet = Query(predicates, columns);
149 if (resultSet == nullptr) {
150 SGLOGI("failed to get appInfo");
151 return DB_OPT_ERR;
152 }
153 AppInfoTableInfo table;
154 int32_t ret = GetResultSetTableInfo(resultSet, table);
155 if (ret != SUCCESS) {
156 return ret;
157 }
158 while (resultSet->GoToNextRow() == NativeRdb::E_OK) {
159 AppInfo info {};
160 resultSet->GetString(table.appNameIndex, info.appName);
161 resultSet->GetString(table.appHashIndex, info.appHash);
162 std::string attrStr;
163 std::vector<std::string> tmpVec;
164 resultSet->GetString(table.appAttrIndex, attrStr);
165 SplitStr(attrStr, ",", tmpVec);
166 info.attrs = tmpVec;
167 resultSet->GetInt(table.appIsGlobalAppIndex, info.isGlobalApp);
168 infos.emplace_back(info);
169 }
170 resultSet->Close();
171 return SUCCESS;
172 }
173
DeleteAppInfoByNameAndGlobbalFlag(const std::string & appName,int isGlobalApp)174 int ConfigDatabaseHelper::DeleteAppInfoByNameAndGlobbalFlag(const std::string &appName, int isGlobalApp)
175 {
176 SGLOGI("DeleteAppInfoByName, appName=%{public}s", appName.c_str());
177 NativeRdb::RdbPredicates queryPredicates(dbTable_);
178 queryPredicates.EqualTo(APP_NAME, appName);
179 queryPredicates.EqualTo(IS_GLOBAL_APP, isGlobalApp);
180 queryPredicates.OrderByAsc(ID);
181 std::vector<std::string> columns { ID };
182 std::shared_ptr<NativeRdb::ResultSet> resultSet = Query(queryPredicates, columns);
183 if (resultSet == nullptr) {
184 SGLOGI("failed to get event, appName=%{public}s", appName.c_str());
185 return DB_OPT_ERR;
186 }
187 int64_t primaryKey = -1;
188 std::vector<std::string> primaryKeyVec;
189 while (resultSet->GoToNextRow() == NativeRdb::E_OK) {
190 resultSet->GetLong(0, primaryKey);
191 primaryKeyVec.emplace_back(std::to_string(primaryKey));
192 }
193 resultSet->Close();
194 int rowId;
195 NativeRdb::RdbPredicates deletePredicates(dbTable_);
196 deletePredicates.In(ID, primaryKeyVec);
197 deletePredicates.EqualTo(APP_NAME, appName);
198 deletePredicates.EqualTo(IS_GLOBAL_APP, isGlobalApp);
199 int ret = Delete(rowId, deletePredicates);
200 if (ret != NativeRdb::E_OK) {
201 SGLOGE("failed to delete event, appName=%{public}s, ret=%{public}d", appName.c_str(), ret);
202 return DB_OPT_ERR;
203 }
204 return SUCCESS;
205 }
206
DeleteAppInfoByIsGlobalApp(int isGlobalApp)207 int ConfigDatabaseHelper::DeleteAppInfoByIsGlobalApp(int isGlobalApp)
208 {
209 NativeRdb::RdbPredicates queryPredicates(dbTable_);
210 queryPredicates.EqualTo(IS_GLOBAL_APP, isGlobalApp);
211 queryPredicates.OrderByAsc(ID);
212 std::vector<std::string> columns { ID };
213 std::shared_ptr<NativeRdb::ResultSet> resultSet = Query(queryPredicates, columns);
214 if (resultSet == nullptr) {
215 SGLOGI("failed to get resultSet");
216 return DB_OPT_ERR;
217 }
218 int64_t primaryKey = -1;
219 std::vector<std::string> primaryKeyVec;
220 while (resultSet->GoToNextRow() == NativeRdb::E_OK) {
221 resultSet->GetLong(0, primaryKey);
222 primaryKeyVec.emplace_back(std::to_string(primaryKey));
223 }
224 resultSet->Close();
225 int rowId;
226 NativeRdb::RdbPredicates deletePredicates(dbTable_);
227 deletePredicates.In(ID, primaryKeyVec);
228 deletePredicates.EqualTo(IS_GLOBAL_APP, isGlobalApp);
229 int ret = Delete(rowId, deletePredicates);
230 if (ret != NativeRdb::E_OK) {
231 SGLOGE("failed to delete App, ret=%{public}d", ret);
232 return DB_OPT_ERR;
233 }
234 return SUCCESS;
235 }
236
QueryAppInfoByAttribute(const std::string attr,std::vector<AppInfo> & infos)237 int ConfigDatabaseHelper::QueryAppInfoByAttribute(const std::string attr, std::vector<AppInfo> &infos)
238 {
239 NativeRdb::RdbPredicates predicates(dbTable_);
240 std::vector<std::string> columns {APP_NAME, APP_FINGERPRINT, APP_ATTRIBUTES, IS_GLOBAL_APP};
241 std::shared_ptr<NativeRdb::ResultSet> resultSet = Query(predicates, columns);
242 if (resultSet == nullptr) {
243 SGLOGI("failed to get event");
244 return DB_OPT_ERR;
245 }
246 AppInfoTableInfo table;
247 int32_t ret = GetResultSetTableInfo(resultSet, table);
248 if (ret != SUCCESS) {
249 return ret;
250 }
251 while (resultSet->GoToNextRow() == NativeRdb::E_OK) {
252 AppInfo info;
253 std::string attrStr;
254 std::vector<std::string> tmpVec;
255 resultSet->GetString(table.appAttrIndex, attrStr);
256 if (attrStr.find(attr) == std::string::npos) {
257 continue;
258 }
259 SplitStr(attrStr, ",", tmpVec);
260 info.attrs = tmpVec;
261 resultSet->GetString(table.appNameIndex, info.appName);
262 resultSet->GetString(table.appHashIndex, info.appHash);
263 infos.emplace_back(info);
264 }
265 resultSet->Close();
266 return SUCCESS;
267 }
268
SetValuesBucket(const AppInfo & event,NativeRdb::ValuesBucket & values)269 void ConfigDatabaseHelper::SetValuesBucket(const AppInfo &event, NativeRdb::ValuesBucket &values)
270 {
271 std::string attrStr;
272 uint32_t index = 1;
273 // construct attr vector to string, exp: 111,222,333
274 for (auto iter : event.attrs) {
275 attrStr.append(iter);
276 if (index == event.attrs.size()) {
277 break;
278 }
279 attrStr.append(",");
280 index++;
281 }
282 values.PutString(APP_NAME, event.appName);
283 values.PutString(APP_FINGERPRINT, event.appHash);
284 values.PutString(APP_ATTRIBUTES, attrStr);
285 values.PutInt(IS_GLOBAL_APP, event.isGlobalApp);
286 }
287
CreateTable()288 std::string ConfigDatabaseHelper::CreateTable()
289 {
290 std::string table;
291 table.append("CREATE TABLE IF NOT EXISTS ").append(dbTable_);
292 table.append("(").append(ID).append(" INTEGER PRIMARY KEY AUTOINCREMENT, ");
293 table.append(APP_NAME).append(" TEXT NOT NULL, ");
294 table.append(APP_FINGERPRINT).append(" TEXT NOT NULL, ");
295 table.append(APP_ATTRIBUTES).append(" TEXT NOT NULL, ");
296 table.append(IS_GLOBAL_APP).append(" INTEGER NOT NULL)");
297 return table;
298 }
299 } // namespace OHOS::Security::SecurityGuard