1 /*
2 * Copyright (c) 2021-2024 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 "access_token_open_callback.h"
17
18 #include "access_token_error.h"
19 #include "access_token.h"
20 #include "accesstoken_log.h"
21 #include "token_field_const.h"
22
23 namespace OHOS {
24 namespace Security {
25 namespace AccessToken {
26 namespace {
27 static constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, SECURITY_DOMAIN_ACCESSTOKEN, "AccessTokenOpenCallback"};
28 constexpr const char* INTEGER_STR = " integer not null,";
29 constexpr const char* TEXT_STR = " text not null,";
30 // back up name is xxx_slave fixed, can not be changed
31 constexpr const char* DATABASE_NAME_BACK = "access_token_slave.db";
32
33 constexpr const uint32_t FLAG_HANDLE_FROM_ONE_TO_TWO = 1;
34 constexpr const uint32_t FLAG_HANDLE_FROM_TWO_TO_THREE = 1 << 1;
35 constexpr const uint32_t FLAG_HANDLE_FROM_THREE_TO_FOUR = 1 << 2;
36 }
37
CreateHapTokenInfoTable(NativeRdb::RdbStore & rdbStore)38 int32_t AccessTokenOpenCallback::CreateHapTokenInfoTable(NativeRdb::RdbStore& rdbStore)
39 {
40 std::string tableName;
41 AccessTokenDbUtil::GetTableNameByType(AtmDataType::ACCESSTOKEN_HAP_INFO, tableName);
42
43 std::string sql = "create table if not exists " + tableName;
44 sql.append(" (")
45 .append(TokenFiledConst::FIELD_TOKEN_ID)
46 .append(INTEGER_STR)
47 .append(TokenFiledConst::FIELD_USER_ID)
48 .append(INTEGER_STR)
49 .append(TokenFiledConst::FIELD_BUNDLE_NAME)
50 .append(TEXT_STR)
51 .append(TokenFiledConst::FIELD_INST_INDEX)
52 .append(INTEGER_STR)
53 .append(TokenFiledConst::FIELD_DLP_TYPE)
54 .append(INTEGER_STR)
55 .append(TokenFiledConst::FIELD_APP_ID)
56 .append(TEXT_STR)
57 .append(TokenFiledConst::FIELD_DEVICE_ID)
58 .append(TEXT_STR)
59 .append(TokenFiledConst::FIELD_APL)
60 .append(INTEGER_STR)
61 .append(TokenFiledConst::FIELD_TOKEN_VERSION)
62 .append(INTEGER_STR)
63 .append(TokenFiledConst::FIELD_TOKEN_ATTR)
64 .append(INTEGER_STR)
65 .append(TokenFiledConst::FIELD_API_VERSION)
66 .append(INTEGER_STR)
67 .append(TokenFiledConst::FIELD_FORBID_PERM_DIALOG)
68 .append(INTEGER_STR)
69 .append("primary key(")
70 .append(TokenFiledConst::FIELD_TOKEN_ID)
71 .append("))");
72
73 return rdbStore.ExecuteSql(sql);
74 }
75
CreateNativeTokenInfoTable(NativeRdb::RdbStore & rdbStore)76 int32_t AccessTokenOpenCallback::CreateNativeTokenInfoTable(NativeRdb::RdbStore& rdbStore)
77 {
78 std::string tableName;
79 AccessTokenDbUtil::GetTableNameByType(AtmDataType::ACCESSTOKEN_NATIVE_INFO, tableName);
80
81 std::string sql = "create table if not exists " + tableName;
82 sql.append(" (")
83 .append(TokenFiledConst::FIELD_TOKEN_ID)
84 .append(INTEGER_STR)
85 .append(TokenFiledConst::FIELD_PROCESS_NAME)
86 .append(TEXT_STR)
87 .append(TokenFiledConst::FIELD_TOKEN_VERSION)
88 .append(INTEGER_STR)
89 .append(TokenFiledConst::FIELD_TOKEN_ATTR)
90 .append(INTEGER_STR)
91 .append(TokenFiledConst::FIELD_DCAP)
92 .append(TEXT_STR)
93 .append(TokenFiledConst::FIELD_NATIVE_ACLS)
94 .append(TEXT_STR)
95 .append(TokenFiledConst::FIELD_APL)
96 .append(INTEGER_STR)
97 .append("primary key(")
98 .append(TokenFiledConst::FIELD_TOKEN_ID)
99 .append("))");
100
101 return rdbStore.ExecuteSql(sql);
102 }
103
CreatePermissionDefinitionTable(NativeRdb::RdbStore & rdbStore)104 int32_t AccessTokenOpenCallback::CreatePermissionDefinitionTable(NativeRdb::RdbStore& rdbStore)
105 {
106 std::string tableName;
107 AccessTokenDbUtil::GetTableNameByType(AtmDataType::ACCESSTOKEN_PERMISSION_DEF, tableName);
108
109 std::string sql = "create table if not exists " + tableName;
110 sql.append(" (")
111 .append(TokenFiledConst::FIELD_TOKEN_ID)
112 .append(INTEGER_STR)
113 .append(TokenFiledConst::FIELD_PERMISSION_NAME)
114 .append(TEXT_STR)
115 .append(TokenFiledConst::FIELD_BUNDLE_NAME)
116 .append(TEXT_STR)
117 .append(TokenFiledConst::FIELD_GRANT_MODE)
118 .append(INTEGER_STR)
119 .append(TokenFiledConst::FIELD_AVAILABLE_LEVEL)
120 .append(INTEGER_STR)
121 .append(TokenFiledConst::FIELD_PROVISION_ENABLE)
122 .append(INTEGER_STR)
123 .append(TokenFiledConst::FIELD_DISTRIBUTED_SCENE_ENABLE)
124 .append(INTEGER_STR)
125 .append(TokenFiledConst::FIELD_LABEL)
126 .append(TEXT_STR)
127 .append(TokenFiledConst::FIELD_LABEL_ID)
128 .append(INTEGER_STR)
129 .append(TokenFiledConst::FIELD_DESCRIPTION)
130 .append(TEXT_STR)
131 .append(TokenFiledConst::FIELD_DESCRIPTION_ID)
132 .append(INTEGER_STR)
133 .append(TokenFiledConst::FIELD_AVAILABLE_TYPE)
134 .append(INTEGER_STR)
135 .append("primary key(")
136 .append(TokenFiledConst::FIELD_TOKEN_ID)
137 .append(",")
138 .append(TokenFiledConst::FIELD_PERMISSION_NAME)
139 .append("))");
140
141 return rdbStore.ExecuteSql(sql);
142 }
143
CreatePermissionStateTable(NativeRdb::RdbStore & rdbStore)144 int32_t AccessTokenOpenCallback::CreatePermissionStateTable(NativeRdb::RdbStore& rdbStore)
145 {
146 std::string tableName;
147 AccessTokenDbUtil::GetTableNameByType(AtmDataType::ACCESSTOKEN_PERMISSION_STATE, tableName);
148
149 std::string sql = "create table if not exists " + tableName;
150 sql.append(" (")
151 .append(TokenFiledConst::FIELD_TOKEN_ID)
152 .append(INTEGER_STR)
153 .append(TokenFiledConst::FIELD_PERMISSION_NAME)
154 .append(TEXT_STR)
155 .append(TokenFiledConst::FIELD_DEVICE_ID)
156 .append(TEXT_STR)
157 .append(TokenFiledConst::FIELD_GRANT_IS_GENERAL)
158 .append(INTEGER_STR)
159 .append(TokenFiledConst::FIELD_GRANT_STATE)
160 .append(INTEGER_STR)
161 .append(TokenFiledConst::FIELD_GRANT_FLAG)
162 .append(INTEGER_STR)
163 .append("primary key(")
164 .append(TokenFiledConst::FIELD_TOKEN_ID)
165 .append(",")
166 .append(TokenFiledConst::FIELD_PERMISSION_NAME)
167 .append(",")
168 .append(TokenFiledConst::FIELD_DEVICE_ID)
169 .append("))");
170
171 return rdbStore.ExecuteSql(sql);
172 }
173
CreatePermissionRequestToggleStatusTable(NativeRdb::RdbStore & rdbStore)174 int32_t AccessTokenOpenCallback::CreatePermissionRequestToggleStatusTable(NativeRdb::RdbStore& rdbStore)
175 {
176 std::string tableName;
177 AccessTokenDbUtil::GetTableNameByType(AtmDataType::ACCESSTOKEN_PERMISSION_REQUEST_TOGGLE_STATUS, tableName);
178
179 std::string sql = "create table if not exists " + tableName;
180 sql.append(" (")
181 .append(TokenFiledConst::FIELD_USER_ID)
182 .append(INTEGER_STR)
183 .append(TokenFiledConst::FIELD_PERMISSION_NAME)
184 .append(TEXT_STR)
185 .append(TokenFiledConst::FIELD_REQUEST_TOGGLE_STATUS)
186 .append(INTEGER_STR)
187 .append("primary key(")
188 .append(TokenFiledConst::FIELD_USER_ID)
189 .append(",")
190 .append(TokenFiledConst::FIELD_PERMISSION_NAME)
191 .append("))");
192
193 return rdbStore.ExecuteSql(sql);
194 }
195
OnCreate(NativeRdb::RdbStore & rdbStore)196 int32_t AccessTokenOpenCallback::OnCreate(NativeRdb::RdbStore& rdbStore)
197 {
198 ACCESSTOKEN_LOG_INFO(LABEL, "DB OnCreate.");
199
200 int32_t res = CreateHapTokenInfoTable(rdbStore);
201 if (res != NativeRdb::E_OK) {
202 ACCESSTOKEN_LOG_ERROR(LABEL, "Failed to create table hap_token_info_table.");
203 return res;
204 }
205
206 res = CreateNativeTokenInfoTable(rdbStore);
207 if (res != NativeRdb::E_OK) {
208 ACCESSTOKEN_LOG_ERROR(LABEL, "Failed to create table native_token_info_table.");
209 return res;
210 }
211
212 res = CreatePermissionDefinitionTable(rdbStore);
213 if (res != NativeRdb::E_OK) {
214 ACCESSTOKEN_LOG_ERROR(LABEL, "Failed to create table permission_definition_table.");
215 return res;
216 }
217
218 res = CreatePermissionStateTable(rdbStore);
219 if (res != NativeRdb::E_OK) {
220 ACCESSTOKEN_LOG_ERROR(LABEL, "Failed to create table permission_state_table.");
221 return res;
222 }
223
224 res = CreatePermissionRequestToggleStatusTable(rdbStore);
225 if (res != NativeRdb::E_OK) {
226 ACCESSTOKEN_LOG_ERROR(LABEL, "Failed to create table permission_request_toggle_status_table.");
227 return res;
228 }
229
230 std::string dbBackPath = std::string(DATABASE_PATH) + std::string(DATABASE_NAME_BACK);
231 if (access(dbBackPath.c_str(), NativeRdb::E_OK) != 0) {
232 return 0;
233 }
234
235 // if OnCreate solution found back up db, restore from backup, may be origin db has lost
236 ACCESSTOKEN_LOG_WARN(LABEL, "Detech origin database disappear, restore from backup!");
237
238 res = rdbStore.Restore("");
239 if (res != NativeRdb::E_OK) {
240 ACCESSTOKEN_LOG_ERROR(LABEL, "Db restore failed, res is %{public}d.", res);
241 }
242
243 ACCESSTOKEN_LOG_WARN(LABEL, "Database restore from backup success!");
244
245 return 0;
246 }
247
AddAvailableTypeColumn(NativeRdb::RdbStore & rdbStore)248 int32_t AccessTokenOpenCallback::AddAvailableTypeColumn(NativeRdb::RdbStore& rdbStore)
249 {
250 std::string tableName;
251 AccessTokenDbUtil::GetTableNameByType(AtmDataType::ACCESSTOKEN_PERMISSION_DEF, tableName);
252
253 // check if column available_type exsit
254 std::string checkSql = "SELECT 1 FROM " + tableName + " WHERE " +
255 TokenFiledConst::FIELD_AVAILABLE_TYPE + "=" + std::to_string(ATokenAvailableTypeEnum::NORMAL);
256
257 int32_t checkRes = rdbStore.ExecuteSql(checkSql);
258 ACCESSTOKEN_LOG_INFO(LABEL, "Check result is %{public}d.", checkRes);
259 if (checkRes == NativeRdb::E_OK) {
260 // success means there exsit column available_type in table
261 return NativeRdb::E_OK;
262 }
263
264 // alter table add column
265 std::string sql = "alter table " + tableName + " add column " +
266 TokenFiledConst::FIELD_AVAILABLE_TYPE + " integer default " + std::to_string(ATokenAvailableTypeEnum::NORMAL);
267
268 int32_t res = rdbStore.ExecuteSql(sql);
269 ACCESSTOKEN_LOG_INFO(LABEL, "Insert column result is %{public}d.", res);
270
271 return res;
272 }
273
AddRequestToggleStatusColumn(NativeRdb::RdbStore & rdbStore)274 int32_t AccessTokenOpenCallback::AddRequestToggleStatusColumn(NativeRdb::RdbStore& rdbStore)
275 {
276 std::string tableName;
277 AccessTokenDbUtil::GetTableNameByType(AtmDataType::ACCESSTOKEN_PERMISSION_REQUEST_TOGGLE_STATUS, tableName);
278
279 // check if column status exsit
280 std::string checkSql = "SELECT 1 FROM " + tableName + " WHERE " +
281 TokenFiledConst::FIELD_REQUEST_TOGGLE_STATUS + "=" + std::to_string(0);
282
283 int32_t checkRes = rdbStore.ExecuteSql(checkSql);
284 ACCESSTOKEN_LOG_INFO(LABEL, "Check result is %{public}d.", checkRes);
285 if (checkRes == NativeRdb::E_OK) {
286 // success means there exsit column status in table
287 return NativeRdb::E_OK;
288 }
289
290 // alter table add column
291 std::string sql = "alter table " + tableName + " add column " +
292 TokenFiledConst::FIELD_REQUEST_TOGGLE_STATUS + " integer default " + std::to_string(0); // 0: close
293
294 int32_t res = rdbStore.ExecuteSql(sql);
295 ACCESSTOKEN_LOG_INFO(LABEL, "Insert column result is %{public}d.", res);
296
297 return res;
298 }
299
AddPermDialogCapColumn(NativeRdb::RdbStore & rdbStore)300 int32_t AccessTokenOpenCallback::AddPermDialogCapColumn(NativeRdb::RdbStore& rdbStore)
301 {
302 std::string tableName;
303 AccessTokenDbUtil::GetTableNameByType(AtmDataType::ACCESSTOKEN_HAP_INFO, tableName);
304
305 // check if column perm_dialog_cap_state exsit
306 std::string checkSql = "SELECT 1 FROM " + tableName + " WHERE " +
307 TokenFiledConst::FIELD_FORBID_PERM_DIALOG + "=" + std::to_string(0);
308
309 int32_t checkRes = rdbStore.ExecuteSql(checkSql);
310 ACCESSTOKEN_LOG_INFO(LABEL, "Check result is %{public}d.", checkRes);
311 if (checkRes == NativeRdb::E_OK) {
312 // success means there exsit column perm_dialog_cap_state in table
313 return NativeRdb::E_OK;
314 }
315
316 // alter table add column
317 std::string sql = "alter table " + tableName + " add column " +
318 TokenFiledConst::FIELD_FORBID_PERM_DIALOG + " integer default " + std::to_string(false);
319
320 int32_t res = rdbStore.ExecuteSql(sql);
321 ACCESSTOKEN_LOG_INFO(LABEL, "Insert column result is %{public}d.", res);
322
323 return res;
324 }
325
HandleUpdateWithFlag(NativeRdb::RdbStore & rdbStore,uint32_t flag)326 int32_t AccessTokenOpenCallback::HandleUpdateWithFlag(NativeRdb::RdbStore& rdbStore, uint32_t flag)
327 {
328 int32_t res = NativeRdb::E_OK;
329
330 if ((flag & FLAG_HANDLE_FROM_ONE_TO_TWO) == FLAG_HANDLE_FROM_ONE_TO_TWO) {
331 res = AddAvailableTypeColumn(rdbStore);
332 if (res != NativeRdb::E_OK) {
333 ACCESSTOKEN_LOG_ERROR(LABEL, "Failed to add column available_type.");
334 return res;
335 }
336
337 res = AddPermDialogCapColumn(rdbStore);
338 if (res != NativeRdb::E_OK) {
339 ACCESSTOKEN_LOG_ERROR(LABEL, "Failed to add column perm_dialog_cap_state.");
340 return res;
341 }
342 }
343
344 if ((flag & FLAG_HANDLE_FROM_TWO_TO_THREE) == FLAG_HANDLE_FROM_TWO_TO_THREE) {
345 res = CreatePermissionRequestToggleStatusTable(rdbStore);
346 if (res != NativeRdb::E_OK) {
347 ACCESSTOKEN_LOG_ERROR(LABEL, "Failed to create table permission_request_toggle_status_table.");
348 return res;
349 }
350 }
351
352 if ((flag & FLAG_HANDLE_FROM_THREE_TO_FOUR) == FLAG_HANDLE_FROM_THREE_TO_FOUR) {
353 res = AddRequestToggleStatusColumn(rdbStore);
354 if (res != NativeRdb::E_OK) {
355 ACCESSTOKEN_LOG_ERROR(LABEL, "Failed to add column status.");
356 return res;
357 }
358 }
359
360 return res;
361 }
362
UpdateFromVersionOne(NativeRdb::RdbStore & rdbStore,int32_t targetVersion)363 int32_t AccessTokenOpenCallback::UpdateFromVersionOne(NativeRdb::RdbStore& rdbStore, int32_t targetVersion)
364 {
365 int32_t res = 0;
366 uint32_t flag = 0;
367
368 switch (targetVersion) {
369 case DATABASE_VERSION_2:
370 flag = FLAG_HANDLE_FROM_ONE_TO_TWO;
371 res = HandleUpdateWithFlag(rdbStore, flag);
372 if (res != NativeRdb::E_OK) {
373 return res;
374 }
375 break;
376
377 case DATABASE_VERSION_3:
378 flag = FLAG_HANDLE_FROM_ONE_TO_TWO + FLAG_HANDLE_FROM_TWO_TO_THREE;
379 res = HandleUpdateWithFlag(rdbStore, flag);
380 if (res != NativeRdb::E_OK) {
381 return res;
382 }
383 break;
384
385 case DATABASE_VERSION_4:
386 flag = FLAG_HANDLE_FROM_ONE_TO_TWO + FLAG_HANDLE_FROM_TWO_TO_THREE + FLAG_HANDLE_FROM_THREE_TO_FOUR;
387 res = HandleUpdateWithFlag(rdbStore, flag);
388 if (res != NativeRdb::E_OK) {
389 return res;
390 }
391 break;
392
393 default:
394 break;
395 }
396
397 return res;
398 }
399
UpdateFromVersionTwo(NativeRdb::RdbStore & rdbStore,int32_t targetVersion)400 int32_t AccessTokenOpenCallback::UpdateFromVersionTwo(NativeRdb::RdbStore& rdbStore, int32_t targetVersion)
401 {
402 int32_t res = 0;
403 uint32_t flag = 0;
404
405 switch (targetVersion) {
406 case DATABASE_VERSION_3:
407 flag = FLAG_HANDLE_FROM_TWO_TO_THREE;
408 res = HandleUpdateWithFlag(rdbStore, flag);
409 if (res != NativeRdb::E_OK) {
410 return res;
411 }
412 break;
413
414 case DATABASE_VERSION_4:
415 flag = FLAG_HANDLE_FROM_TWO_TO_THREE + FLAG_HANDLE_FROM_THREE_TO_FOUR;
416 res = HandleUpdateWithFlag(rdbStore, flag);
417 if (res != NativeRdb::E_OK) {
418 return res;
419 }
420 break;
421
422 default:
423 break;
424 }
425
426 return res;
427 }
428
UpdateFromVersionThree(NativeRdb::RdbStore & rdbStore,int32_t targetVersion)429 int32_t AccessTokenOpenCallback::UpdateFromVersionThree(NativeRdb::RdbStore& rdbStore, int32_t targetVersion)
430 {
431 int32_t res = 0;
432 uint32_t flag = 0;
433
434 switch (targetVersion) {
435 case DATABASE_VERSION_4:
436 flag = FLAG_HANDLE_FROM_THREE_TO_FOUR;
437 res = HandleUpdateWithFlag(rdbStore, flag);
438 if (res != NativeRdb::E_OK) {
439 return res;
440 }
441 break;
442
443 default:
444 break;
445 }
446
447 return res;
448 }
449
OnUpgrade(NativeRdb::RdbStore & rdbStore,int32_t currentVersion,int32_t targetVersion)450 int32_t AccessTokenOpenCallback::OnUpgrade(NativeRdb::RdbStore& rdbStore, int32_t currentVersion, int32_t targetVersion)
451 {
452 ACCESSTOKEN_LOG_INFO(LABEL, "DB OnUpgrade from currentVersion %{public}d to targetVersion %{public}d.",
453 currentVersion, targetVersion);
454
455 int32_t res = 0;
456
457 switch (currentVersion) {
458 case DATABASE_VERSION_1:
459 res = UpdateFromVersionOne(rdbStore, targetVersion);
460 if (res != 0) {
461 return res;
462 }
463 break;
464
465 case DATABASE_VERSION_2:
466 res = UpdateFromVersionTwo(rdbStore, targetVersion);
467 if (res != 0) {
468 return res;
469 }
470 break;
471
472 case DATABASE_VERSION_3:
473 res = UpdateFromVersionThree(rdbStore, targetVersion);
474 if (res != 0) {
475 return res;
476 }
477 break;
478
479 default:
480 break;
481 }
482
483 return res;
484 }
485 } // namespace AccessToken
486 } // namespace Security
487 } // namespace OHOS
488