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;
82 ret = save_smack_rules(*pp_db);
88 * Commit database modification.
89 * If previous operation returned an error try to rollback changes.
91 * @ingroup RDB internal functions
93 * @param p_db pointer to a SQLite3 database object
94 * @param i_session_ret session return code
95 * @return PC_OPERATION_SUCCESS on success,
96 * error code otherwise
98 static int rdb_end(sqlite3 *p_db, int i_session_ret)
102 int ret = PC_OPERATION_SUCCESS;
104 // No error during the session, make updates
105 if(i_session_ret == PC_OPERATION_SUCCESS) {
106 ret = update_rules_in_db(p_db);
107 if(ret != PC_OPERATION_SUCCESS) {
108 C_LOGE("RDB: Error during updating rules in the database: %d", ret);
113 ret = update_smack_rules(p_db);
114 if(ret != PC_OPERATION_SUCCESS) {
115 C_LOGE("RDB: Error updating smack rules: %d", ret);
122 // End transaction in a way
123 // that depends on the ret and i_session_ret code.
124 if(i_session_ret == PC_OPERATION_SUCCESS &&
125 ret == PC_OPERATION_SUCCESS) {
126 if(sqlite3_exec(p_db, "COMMIT TRANSACTION", 0, 0, 0)
128 C_LOGE("RDB: Error during transaction commit: %s",
129 sqlite3_errmsg(p_db));
130 ret = PC_ERR_DB_CONNECTION;
133 } else if(i_session_ret == PC_ERR_DB_CONNECTION ||
134 ret == PC_ERR_DB_CONNECTION) {
135 // Life is pointless. I can't even rollback...
136 C_LOGE("RDB: No rollback nor commit.");
137 ret = PC_ERR_DB_CONNECTION;
140 // Some other error code
141 if(sqlite3_exec(p_db, "ROLLBACK TRANSACTION", 0, 0, 0)
143 C_LOGE("RDB: Error during transaction rollback: %s",
144 sqlite3_errmsg(p_db));
145 if(ret == PC_OPERATION_SUCCESS)
146 ret = PC_ERR_DB_CONNECTION;
150 if(sqlite3_close(p_db)) {
151 C_LOGE("RDB: Error during closing the database. Error: %s",
152 sqlite3_errmsg(p_db));
153 if(ret == PC_OPERATION_SUCCESS)
154 ret = PC_ERR_DB_CONNECTION;
161 * Finish database modification.
162 * If global transaction is opened update session return code,
163 * otherwise end the transaction.
165 * @ingroup RDB internal functions
167 * @param p_db pointer to a SQLite3 database object
168 * @param i_session_ret session return code
169 * @return PC_OPERATION_SUCCESS on success,
170 * error code otherwise
172 static int rdb_finish(sqlite3 *p_db, int i_session_ret)
175 if(i_session_ret_code__ == PC_OPERATION_SUCCESS)
176 i_session_ret_code__ = i_session_ret;
177 return i_session_ret;
179 int ret = rdb_end(p_db, i_session_ret);
180 return i_session_ret != PC_OPERATION_SUCCESS ? i_session_ret : ret;
185 int rdb_modification_start(void)
188 // We have to finish the previous session:
189 C_LOGW("RDB: rdb_modification_finish was not called!");
190 rdb_modification_finish();
193 return rdb_begin(&p_db__, RDB_TRANSACTION_EXCLUSIVE);
197 int rdb_modification_finish(void)
200 int ret = rdb_end(p_db__, i_session_ret_code__);
202 i_session_ret_code__ = PC_OPERATION_SUCCESS;
205 return PC_OPERATION_SUCCESS;
210 int rdb_add_application(const char *const s_label_name)
212 RDB_LOG_ENTRY_PARAM("%s", s_label_name);
214 int ret = PC_ERR_DB_OPERATION;
215 sqlite3 *p_db = NULL;
217 ret = rdb_begin(&p_db, RDB_TRANSACTION_EXCLUSIVE);
218 if(ret != PC_OPERATION_SUCCESS) goto finish;
220 ret = check_app_label_internal(p_db, s_label_name);
221 if(ret == PC_ERR_DB_LABEL_TAKEN) {
222 ret = PC_OPERATION_SUCCESS;
223 C_LOGW("RDB: There is an application with label: %s", s_label_name);
225 } else if(ret == PC_OPERATION_SUCCESS) {
226 // There is no such label yet.
227 ret = add_app_internal(p_db, s_label_name);
228 if(ret != PC_OPERATION_SUCCESS) goto finish;
231 ret = add_modified_label_internal(p_db, s_label_name);
234 return rdb_finish(p_db, ret);
238 int rdb_remove_application(const char *const s_label_name)
240 RDB_LOG_ENTRY_PARAM("%s", s_label_name);
242 int ret = PC_ERR_DB_OPERATION;
243 sqlite3 *p_db = NULL;
245 ret = rdb_begin(&p_db, RDB_TRANSACTION_EXCLUSIVE);
246 if(ret != PC_OPERATION_SUCCESS) goto finish;
248 ret = add_modified_label_internal(p_db, s_label_name);
249 if(ret != PC_OPERATION_SUCCESS) goto finish;
251 ret = add_modified_apps_path_internal(p_db, s_label_name);
252 if(ret != PC_OPERATION_SUCCESS) goto finish;
254 ret = remove_app_internal(p_db, s_label_name);
257 return rdb_finish(p_db, ret);
261 int rdb_add_path(const char *const s_owner_label_name,
262 const char *const s_path_label_name,
263 const char *const s_path,
264 const char *const s_access,
265 const char *const s_access_reverse,
266 const char *const s_type)
268 RDB_LOG_ENTRY_PARAM("%s %s %s %s %s %s",
269 s_owner_label_name, s_path_label_name,
270 s_path, s_access, s_access_reverse, s_type);
272 int ret = PC_ERR_DB_OPERATION;
273 sqlite3 *p_db = NULL;
275 ret = rdb_begin(&p_db, RDB_TRANSACTION_EXCLUSIVE);
276 if(ret != PC_OPERATION_SUCCESS) goto finish;
278 ret = add_path_internal(p_db,
285 if(ret != PC_OPERATION_SUCCESS) goto finish;
287 ret = add_modified_label_internal(p_db, s_path_label_name);
290 return rdb_finish(p_db, ret);
294 int rdb_add_permission_rules(const char *const s_permission_name,
295 const char *const s_permission_type_name,
296 const char *const *const pp_smack_rules)
298 RDB_LOG_ENTRY_PARAM("%s %s", s_permission_name, s_permission_type_name);
300 int ret = PC_ERR_DB_OPERATION;
301 sqlite3 *p_db = NULL;
302 sqlite3_int64 permission_id = -1;
304 ret = rdb_begin(&p_db, RDB_TRANSACTION_EXCLUSIVE);
305 if(ret != PC_OPERATION_SUCCESS) goto finish;
307 ret = add_permission_internal(p_db,
309 s_permission_type_name);
310 if(ret != PC_OPERATION_SUCCESS) goto finish;
312 ret = get_permission_id_internal(p_db,
314 s_permission_type_name,
316 if(ret != PC_OPERATION_SUCCESS) goto finish;
318 ret = add_modified_permission_internal(p_db, permission_id);
319 if(ret != PC_OPERATION_SUCCESS) goto finish;
321 if(pp_smack_rules != NULL) {
322 ret = add_permission_rules_internal(p_db,
328 return rdb_finish(p_db, ret);
332 int rdb_enable_app_permissions(const char *const s_app_label_name,
333 const app_type_t i_permission_type,
334 const char *const *const pp_permissions_list,
335 const bool b_is_volatile)
337 RDB_LOG_ENTRY_PARAM("%s %d %d", s_app_label_name, i_permission_type, (int)b_is_volatile);
339 int ret = PC_ERR_DB_OPERATION;
340 sqlite3 *p_db = NULL;
341 char *s_permission_name = NULL;
345 const char *s_permission_type_name = app_type_name(i_permission_type);
346 const char *s_permission_group_type_name = app_type_group_name(i_permission_type);
348 ret = rdb_begin(&p_db, RDB_TRANSACTION_EXCLUSIVE);
349 if(ret != PC_OPERATION_SUCCESS) goto finish;
351 ret = get_app_id_internal(p_db, &i_app_id, s_app_label_name);
352 if(ret != PC_OPERATION_SUCCESS) goto finish;
354 // Add permissions specific for the permission type:
355 ret = change_app_permission_internal(p_db,
357 s_permission_type_name,
358 s_permission_type_name,
361 if(ret != PC_OPERATION_SUCCESS) goto finish;
363 // Add permissions from the list:
364 for(i = 0; pp_permissions_list[i] != NULL; ++i) {
365 // Ignore empty lines
366 if(strspn(pp_permissions_list[i], " \t\n")
367 == strlen(pp_permissions_list[i]))
370 ret = base_name_from_perm(pp_permissions_list[i], &s_permission_name);
371 if(ret != PC_OPERATION_SUCCESS) goto finish;
373 ret = change_app_permission_internal(p_db,
376 s_permission_group_type_name,
379 free(s_permission_name);
380 if(ret != PC_OPERATION_SUCCESS) goto finish;
383 ret = add_modified_label_internal(p_db, s_app_label_name);
386 return rdb_finish(p_db, ret);
390 int rdb_disable_app_permissions(const char *const s_app_label_name,
391 const app_type_t i_permission_type,
392 const char *const *const pp_permissions_list)
394 RDB_LOG_ENTRY_PARAM("%s %d", s_app_label_name, i_permission_type);
396 int ret = PC_ERR_DB_OPERATION;
397 sqlite3 *p_db = NULL;
398 char *s_permission_name = NULL;
400 const char *s_permission_group_type_name = app_type_group_name(i_permission_type);
402 ret = rdb_begin(&p_db, RDB_TRANSACTION_EXCLUSIVE);
403 if(ret != PC_OPERATION_SUCCESS) goto finish;
405 ret = get_app_id_internal(p_db, &i_app_id, s_app_label_name);
406 if(ret != PC_OPERATION_SUCCESS) goto finish;
408 for(i = 0; pp_permissions_list[i] != NULL ; ++i) {
409 // Ignore empty lines
410 if(strspn(pp_permissions_list[i], " \t\n")
411 == strlen(pp_permissions_list[i]))
414 ret = base_name_from_perm(pp_permissions_list[i], &s_permission_name);
415 if(ret != PC_OPERATION_SUCCESS) goto finish;
417 ret = switch_app_permission_internal(p_db,
420 s_permission_group_type_name,
422 free(s_permission_name);
423 if(ret != PC_OPERATION_SUCCESS) goto finish;
426 ret = add_modified_label_internal(p_db, s_app_label_name);
429 return rdb_finish(p_db, ret);
433 int rdb_revoke_app_permissions(const char *const s_app_label_name)
435 RDB_LOG_ENTRY_PARAM("%s", s_app_label_name);
437 int ret = PC_ERR_DB_OPERATION;
438 sqlite3 *p_db = NULL;
440 ret = rdb_begin(&p_db, RDB_TRANSACTION_EXCLUSIVE);
441 if(ret != PC_OPERATION_SUCCESS) goto finish;
443 ret = add_modified_label_internal(p_db, s_app_label_name);
444 if(ret != PC_OPERATION_SUCCESS) goto finish;
446 ret = add_modified_apps_path_internal(p_db, s_app_label_name);
447 if(ret != PC_OPERATION_SUCCESS) goto finish;
449 ret = revoke_app_permissions_internal(p_db, s_app_label_name);
452 return rdb_finish(p_db, ret);
456 int rdb_reset_app_permissions(const char *const s_app_label_name)
458 RDB_LOG_ENTRY_PARAM("%s", s_app_label_name);
460 int ret = PC_ERR_DB_OPERATION;
461 sqlite3 *p_db = NULL;
463 ret = rdb_begin(&p_db, RDB_TRANSACTION_EXCLUSIVE);
464 if(ret != PC_OPERATION_SUCCESS) goto finish;
466 ret = reset_app_permissions_internal(p_db, s_app_label_name);
467 if(ret != PC_OPERATION_SUCCESS) goto finish;
469 ret = add_modified_label_internal(p_db, s_app_label_name);
472 return rdb_finish(p_db, ret);
476 int rdb_add_additional_rules(const char *const *const pp_smack_rules)
480 int ret = PC_ERR_DB_OPERATION;
481 sqlite3 *p_db = NULL;
483 ret = rdb_begin(&p_db, RDB_TRANSACTION_EXCLUSIVE);
484 if(ret != PC_OPERATION_SUCCESS) goto finish;
486 ret = add_additional_rules_internal(p_db,
490 return rdb_finish(p_db, ret);
493 int rdb_app_has_permission(const char *const s_app_label_name,
494 const char *const s_permission_type_name,
495 const char *const s_permission_name,
496 bool *const p_is_enabled)
498 RDB_LOG_ENTRY_PARAM("%s %s %s", s_app_label_name,
499 s_permission_type_name, s_permission_name);
500 int ret = PC_ERR_DB_OPERATION;
501 sqlite3 *p_db = NULL;
503 ret = rdb_begin(&p_db, RDB_TRANSACTION_SHARED_READ); //shared readonly transaction
504 if(ret != PC_OPERATION_SUCCESS) goto finish;
506 ret = check_app_has_permission_internal(p_db,
509 s_permission_type_name,
513 return rdb_finish(p_db, ret);