2 * libprivilege control, rules database
4 * Copyright (c) 2000 - 2013 Samsung Electronics Co., Ltd All Rights Reserved
6 * Contact: Jan Olszak <j.olszak@samsung.com>
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
12 * http://www.apache.org/licenses/LICENSE-2.0
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
24 * @author Jan Olszak (j.olszak@samsung.com)
26 * @brief This file contains declaration of the API to rules database.
31 #include "privilege-control.h"
32 #include "rules-db-internals.h"
34 static sqlite3 *p_db__ = NULL;
35 static int i_session_ret_code__ = PC_OPERATION_SUCCESS;
38 RDB_TRANSACTION_EXCLUSIVE,
39 RDB_TRANSACTION_SHARED_READ
40 } rdb_transaction_type_t;
43 * Prepare to modify the database.
45 * @ingroup RDB internal functions
47 * @param pp_db pointer to a pointer to a SQLite3 database object
48 * @param transaction_type indicates whether the transaction is exclusive or shared
49 * @return PC_OPERATION_SUCCESS on success, error code otherwise
51 static int rdb_begin(sqlite3 **pp_db, rdb_transaction_type_t transaction_type)
55 // If rdb_modification_start was called we use a global connection.
58 return PC_OPERATION_SUCCESS;
61 int ret = open_rdb_connection(pp_db);
62 if(ret != PC_OPERATION_SUCCESS) return ret;
64 if(transaction_type == RDB_TRANSACTION_EXCLUSIVE) {
65 ret = sqlite3_exec(*pp_db, "BEGIN EXCLUSIVE TRANSACTION", 0, 0, 0);
67 else if(transaction_type == RDB_TRANSACTION_SHARED_READ) {
68 ret = sqlite3_exec(*pp_db, "BEGIN DEFERRED TRANSACTION", 0, 0, 0);
71 C_LOGE("RDB: Bad transaction type specified: %d",
72 (int)transaction_type);
73 return PC_ERR_INVALID_PARAM;
76 if(ret != SQLITE_OK) {
77 C_LOGE("RDB: Error during transaction begin: %s",
78 sqlite3_errmsg(*pp_db));
79 return PC_ERR_DB_CONNECTION;
87 * Commit database modification.
88 * If previous operation returned an error try to rollback changes.
90 * @ingroup RDB internal functions
92 * @param p_db pointer to a SQLite3 database object
93 * @param i_session_ret session return code
94 * @return PC_OPERATION_SUCCESS on success,
95 * error code otherwise
97 static int rdb_end(sqlite3 *p_db, int i_session_ret)
101 int ret = PC_OPERATION_SUCCESS;
103 // No error during the session, make updates
104 if(i_session_ret == PC_OPERATION_SUCCESS) {
105 ret = update_rules_in_db(p_db);
106 if(ret != PC_OPERATION_SUCCESS) {
107 C_LOGE("RDB: Error during updating rules in the database: %d", ret);
112 ret = update_smack_rules(p_db);
113 if(ret != PC_OPERATION_SUCCESS) {
114 C_LOGE("RDB: Error updating smack rules: %d", ret);
121 // End transaction in a way
122 // that depends on the ret and i_session_ret code.
123 if(i_session_ret == PC_OPERATION_SUCCESS &&
124 ret == PC_OPERATION_SUCCESS) {
125 if(sqlite3_exec(p_db, "COMMIT TRANSACTION", 0, 0, 0)
127 C_LOGE("RDB: Error during transaction commit: %s",
128 sqlite3_errmsg(p_db));
129 ret = PC_ERR_DB_CONNECTION;
132 } else if(i_session_ret == PC_ERR_DB_CONNECTION ||
133 ret == PC_ERR_DB_CONNECTION) {
134 // Life is pointless. I can't even rollback...
135 C_LOGE("RDB: No rollback nor commit.");
136 ret = PC_ERR_DB_CONNECTION;
139 // Some other error code
140 if(sqlite3_exec(p_db, "ROLLBACK TRANSACTION", 0, 0, 0)
142 C_LOGE("RDB: Error during transaction rollback: %s",
143 sqlite3_errmsg(p_db));
144 if(ret == PC_OPERATION_SUCCESS)
145 ret = PC_ERR_DB_CONNECTION;
149 if(sqlite3_close(p_db)) {
150 C_LOGE("RDB: Error during closing the database. Error: %s",
151 sqlite3_errmsg(p_db));
152 if(ret == PC_OPERATION_SUCCESS)
153 ret = PC_ERR_DB_CONNECTION;
160 * Finish database modification.
161 * If global transaction is opened update session return code,
162 * otherwise end the transaction.
164 * @ingroup RDB internal functions
166 * @param p_db pointer to a SQLite3 database object
167 * @param i_session_ret session return code
168 * @return PC_OPERATION_SUCCESS on success,
169 * error code otherwise
171 static int rdb_finish(sqlite3 *p_db, int i_session_ret)
174 if(i_session_ret_code__ == PC_OPERATION_SUCCESS)
175 i_session_ret_code__ = i_session_ret;
176 return i_session_ret;
178 int ret = rdb_end(p_db, i_session_ret);
179 return i_session_ret != PC_OPERATION_SUCCESS ? i_session_ret : ret;
184 int rdb_modification_start(void)
187 // We have to finish the previous session:
188 C_LOGW("RDB: rdb_modification_finish was not called!");
189 rdb_modification_finish();
192 return rdb_begin(&p_db__, RDB_TRANSACTION_EXCLUSIVE);
196 int rdb_modification_finish(void)
199 int ret = rdb_end(p_db__, i_session_ret_code__);
201 i_session_ret_code__ = PC_OPERATION_SUCCESS;
204 return PC_OPERATION_SUCCESS;
209 int rdb_add_application(const char *const s_label_name)
211 RDB_LOG_ENTRY_PARAM("%s", s_label_name);
213 int ret = PC_ERR_DB_OPERATION;
214 sqlite3 *p_db = NULL;
216 ret = rdb_begin(&p_db, RDB_TRANSACTION_EXCLUSIVE);
217 if(ret != PC_OPERATION_SUCCESS) goto finish;
219 ret = check_app_label_internal(p_db, s_label_name);
220 if(ret == PC_ERR_DB_LABEL_TAKEN) {
221 ret = PC_OPERATION_SUCCESS;
222 C_LOGW("RDB: There is an application with label: %s", s_label_name);
224 } else if(ret == PC_OPERATION_SUCCESS) {
225 // There is no such label yet.
226 ret = add_app_internal(p_db, s_label_name);
227 if(ret != PC_OPERATION_SUCCESS) goto finish;
230 ret = add_modified_label_internal(p_db, s_label_name);
233 return rdb_finish(p_db, ret);
237 int rdb_remove_application(const char *const s_label_name)
239 RDB_LOG_ENTRY_PARAM("%s", s_label_name);
241 int ret = PC_ERR_DB_OPERATION;
242 sqlite3 *p_db = NULL;
244 ret = rdb_begin(&p_db, RDB_TRANSACTION_EXCLUSIVE);
245 if(ret != PC_OPERATION_SUCCESS) goto finish;
247 ret = add_modified_label_internal(p_db, s_label_name);
248 if(ret != PC_OPERATION_SUCCESS) goto finish;
250 ret = add_modified_apps_path_internal(p_db, s_label_name);
251 if(ret != PC_OPERATION_SUCCESS) goto finish;
253 ret = remove_app_internal(p_db, s_label_name);
256 return rdb_finish(p_db, ret);
260 int rdb_add_path(const char *const s_owner_label_name,
261 const char *const s_path_label_name,
262 const char *const s_path,
263 const char *const s_access,
264 const char *const s_access_reverse,
265 const char *const s_type)
267 RDB_LOG_ENTRY_PARAM("%s %s %s %s %s %s",
268 s_owner_label_name, s_path_label_name,
269 s_path, s_access, s_access_reverse, s_type);
271 int ret = PC_ERR_DB_OPERATION;
272 sqlite3 *p_db = NULL;
274 ret = rdb_begin(&p_db, RDB_TRANSACTION_EXCLUSIVE);
275 if(ret != PC_OPERATION_SUCCESS) goto finish;
277 ret = add_path_internal(p_db,
284 if(ret != PC_OPERATION_SUCCESS) goto finish;
286 ret = add_modified_label_internal(p_db, s_path_label_name);
289 return rdb_finish(p_db, ret);
293 int rdb_get_app_paths(const char *const s_app_label_name,
294 const char *const s_app_path_type_name,
297 RDB_LOG_ENTRY_PARAM("%s %s", s_app_label_name, s_app_path_type_name);
301 sqlite3 *p_db = NULL;
303 ret = rdb_begin(&p_db, RDB_TRANSACTION_SHARED_READ);
304 if (ret != PC_OPERATION_SUCCESS) goto finish;
306 ret = get_app_paths_count_internal(p_db,
308 s_app_path_type_name,
310 if (ret != PC_OPERATION_SUCCESS) goto finish;
312 ret = get_app_paths_internal(p_db, s_app_label_name,
313 s_app_path_type_name,
318 return rdb_finish(p_db, ret);
322 int rdb_add_permission_rules(const char *const s_permission_name,
323 const char *const s_permission_type_name,
324 const char *const *const pp_smack_rules)
326 RDB_LOG_ENTRY_PARAM("%s %s", s_permission_name, s_permission_type_name);
328 int ret = PC_ERR_DB_OPERATION;
329 sqlite3 *p_db = NULL;
330 sqlite3_int64 permission_id = -1;
332 ret = rdb_begin(&p_db, RDB_TRANSACTION_EXCLUSIVE);
333 if(ret != PC_OPERATION_SUCCESS) goto finish;
335 ret = add_permission_internal(p_db,
337 s_permission_type_name);
338 if(ret != PC_OPERATION_SUCCESS) goto finish;
340 ret = get_permission_id_internal(p_db,
342 s_permission_type_name,
344 if(ret != PC_OPERATION_SUCCESS) goto finish;
346 ret = add_modified_permission_internal(p_db, permission_id);
347 if(ret != PC_OPERATION_SUCCESS) goto finish;
349 if(pp_smack_rules != NULL) {
350 ret = add_permission_rules_internal(p_db,
356 return rdb_finish(p_db, ret);
360 int rdb_enable_app_permissions(const char *const s_app_label_name,
361 const app_type_t i_permission_type,
362 const char *const *const pp_permissions_list,
363 const bool b_is_volatile)
365 RDB_LOG_ENTRY_PARAM("%s %d %d", s_app_label_name, i_permission_type, (int)b_is_volatile);
367 int ret = PC_ERR_DB_OPERATION;
368 sqlite3 *p_db = NULL;
369 char *s_permission_name = NULL;
373 const char *s_permission_type_name = app_type_name(i_permission_type);
374 const char *s_permission_group_type_name = app_type_group_name(i_permission_type);
376 ret = rdb_begin(&p_db, RDB_TRANSACTION_EXCLUSIVE);
377 if(ret != PC_OPERATION_SUCCESS) goto finish;
379 ret = get_app_id_internal(p_db, &i_app_id, s_app_label_name);
380 if(ret != PC_OPERATION_SUCCESS) goto finish;
382 // Add permissions specific for the permission type:
383 ret = change_app_permission_internal(p_db,
385 s_permission_type_name,
386 s_permission_type_name,
389 if(ret != PC_OPERATION_SUCCESS) goto finish;
391 // Add permissions from the list:
392 for(i = 0; pp_permissions_list[i] != NULL; ++i) {
393 // Ignore empty lines
394 if(strspn(pp_permissions_list[i], " \t\n")
395 == strlen(pp_permissions_list[i]))
398 ret = base_name_from_perm(pp_permissions_list[i], &s_permission_name);
399 if(ret != PC_OPERATION_SUCCESS) goto finish;
401 ret = change_app_permission_internal(p_db,
404 s_permission_group_type_name,
407 free(s_permission_name);
408 if(ret != PC_OPERATION_SUCCESS) goto finish;
411 ret = add_modified_label_internal(p_db, s_app_label_name);
414 return rdb_finish(p_db, ret);
418 int rdb_disable_app_permissions(const char *const s_app_label_name,
419 const app_type_t i_permission_type,
420 const char *const *const pp_permissions_list)
422 RDB_LOG_ENTRY_PARAM("%s %d", s_app_label_name, i_permission_type);
424 int ret = PC_ERR_DB_OPERATION;
425 sqlite3 *p_db = NULL;
426 char *s_permission_name = NULL;
428 const char *s_permission_group_type_name = app_type_group_name(i_permission_type);
430 ret = rdb_begin(&p_db, RDB_TRANSACTION_EXCLUSIVE);
431 if(ret != PC_OPERATION_SUCCESS) goto finish;
433 ret = get_app_id_internal(p_db, &i_app_id, s_app_label_name);
434 if(ret != PC_OPERATION_SUCCESS) goto finish;
436 for(i = 0; pp_permissions_list[i] != NULL ; ++i) {
437 // Ignore empty lines
438 if(strspn(pp_permissions_list[i], " \t\n")
439 == strlen(pp_permissions_list[i]))
442 ret = base_name_from_perm(pp_permissions_list[i], &s_permission_name);
443 if(ret != PC_OPERATION_SUCCESS) goto finish;
445 ret = switch_app_permission_internal(p_db,
448 s_permission_group_type_name,
450 free(s_permission_name);
451 if(ret != PC_OPERATION_SUCCESS) goto finish;
454 ret = add_modified_label_internal(p_db, s_app_label_name);
457 return rdb_finish(p_db, ret);
461 int rdb_revoke_app_permissions(const char *const s_app_label_name)
463 RDB_LOG_ENTRY_PARAM("%s", s_app_label_name);
465 int ret = PC_ERR_DB_OPERATION;
466 sqlite3 *p_db = NULL;
468 ret = rdb_begin(&p_db, RDB_TRANSACTION_EXCLUSIVE);
469 if(ret != PC_OPERATION_SUCCESS) goto finish;
471 ret = add_modified_label_internal(p_db, s_app_label_name);
472 if(ret != PC_OPERATION_SUCCESS) goto finish;
474 ret = add_modified_apps_path_internal(p_db, s_app_label_name);
475 if(ret != PC_OPERATION_SUCCESS) goto finish;
477 ret = revoke_app_permissions_internal(p_db, s_app_label_name);
480 return rdb_finish(p_db, ret);
484 int rdb_reset_app_permissions(const char *const s_app_label_name)
486 RDB_LOG_ENTRY_PARAM("%s", s_app_label_name);
488 int ret = PC_ERR_DB_OPERATION;
489 sqlite3 *p_db = NULL;
491 ret = rdb_begin(&p_db, RDB_TRANSACTION_EXCLUSIVE);
492 if(ret != PC_OPERATION_SUCCESS) goto finish;
494 ret = reset_app_permissions_internal(p_db, s_app_label_name);
495 if(ret != PC_OPERATION_SUCCESS) goto finish;
497 ret = add_modified_label_internal(p_db, s_app_label_name);
500 return rdb_finish(p_db, ret);
504 int rdb_add_additional_rules(const char *const *const pp_smack_rules)
508 int ret = PC_ERR_DB_OPERATION;
509 sqlite3 *p_db = NULL;
511 ret = rdb_begin(&p_db, RDB_TRANSACTION_EXCLUSIVE);
512 if(ret != PC_OPERATION_SUCCESS) goto finish;
514 // Old rules may disappear, so mark as modified
515 ret = add_modified_additional_rules_internal(p_db);
516 if(ret != PC_OPERATION_SUCCESS) goto finish;
518 ret = add_additional_rules_internal(p_db, pp_smack_rules);
519 if(ret != PC_OPERATION_SUCCESS) goto finish;
521 // New rules appear, so also mark as modified
522 ret = add_modified_additional_rules_internal(p_db);
525 return rdb_finish(p_db, ret);
528 int rdb_app_has_permission(const char *const s_app_label_name,
529 const char *const s_permission_type_name,
530 const char *const s_permission_name,
531 bool *const p_is_enabled)
533 RDB_LOG_ENTRY_PARAM("%s %s %s", s_app_label_name,
534 s_permission_type_name, s_permission_name);
535 int ret = PC_ERR_DB_OPERATION;
536 sqlite3 *p_db = NULL;
538 ret = rdb_begin(&p_db, RDB_TRANSACTION_SHARED_READ); //shared readonly transaction
539 if(ret != PC_OPERATION_SUCCESS) goto finish;
541 ret = check_app_has_permission_internal(p_db,
544 s_permission_type_name,
548 return rdb_finish(p_db, ret);