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_add_permission_rules(const char *const s_permission_name,
294 const char *const s_permission_type_name,
295 const char *const *const pp_smack_rules)
297 RDB_LOG_ENTRY_PARAM("%s %s", s_permission_name, s_permission_type_name);
299 int ret = PC_ERR_DB_OPERATION;
300 sqlite3 *p_db = NULL;
301 sqlite3_int64 permission_id = -1;
303 ret = rdb_begin(&p_db, RDB_TRANSACTION_EXCLUSIVE);
304 if(ret != PC_OPERATION_SUCCESS) goto finish;
306 ret = add_permission_internal(p_db,
308 s_permission_type_name);
309 if(ret != PC_OPERATION_SUCCESS) goto finish;
311 ret = get_permission_id_internal(p_db,
313 s_permission_type_name,
315 if(ret != PC_OPERATION_SUCCESS) goto finish;
317 ret = add_modified_permission_internal(p_db, permission_id);
318 if(ret != PC_OPERATION_SUCCESS) goto finish;
320 if(pp_smack_rules != NULL) {
321 ret = add_permission_rules_internal(p_db,
327 return rdb_finish(p_db, ret);
331 int rdb_enable_app_permissions(const char *const s_app_label_name,
332 const app_type_t i_permission_type,
333 const char *const *const pp_permissions_list,
334 const bool b_is_volatile)
336 RDB_LOG_ENTRY_PARAM("%s %d %d", s_app_label_name, i_permission_type, (int)b_is_volatile);
338 int ret = PC_ERR_DB_OPERATION;
339 sqlite3 *p_db = NULL;
340 char *s_permission_name = NULL;
344 const char *s_permission_type_name = app_type_name(i_permission_type);
345 const char *s_permission_group_type_name = app_type_group_name(i_permission_type);
347 ret = rdb_begin(&p_db, RDB_TRANSACTION_EXCLUSIVE);
348 if(ret != PC_OPERATION_SUCCESS) goto finish;
350 ret = get_app_id_internal(p_db, &i_app_id, s_app_label_name);
351 if(ret != PC_OPERATION_SUCCESS) goto finish;
353 // Add permissions specific for the permission type:
354 ret = change_app_permission_internal(p_db,
356 s_permission_type_name,
357 s_permission_type_name,
360 if(ret != PC_OPERATION_SUCCESS) goto finish;
362 // Add permissions from the list:
363 for(i = 0; pp_permissions_list[i] != NULL; ++i) {
364 // Ignore empty lines
365 if(strspn(pp_permissions_list[i], " \t\n")
366 == strlen(pp_permissions_list[i]))
369 ret = base_name_from_perm(pp_permissions_list[i], &s_permission_name);
370 if(ret != PC_OPERATION_SUCCESS) goto finish;
372 ret = change_app_permission_internal(p_db,
375 s_permission_group_type_name,
378 free(s_permission_name);
379 if(ret != PC_OPERATION_SUCCESS) goto finish;
382 ret = add_modified_label_internal(p_db, s_app_label_name);
385 return rdb_finish(p_db, ret);
389 int rdb_disable_app_permissions(const char *const s_app_label_name,
390 const app_type_t i_permission_type,
391 const char *const *const pp_permissions_list)
393 RDB_LOG_ENTRY_PARAM("%s %d", s_app_label_name, i_permission_type);
395 int ret = PC_ERR_DB_OPERATION;
396 sqlite3 *p_db = NULL;
397 char *s_permission_name = NULL;
399 const char *s_permission_group_type_name = app_type_group_name(i_permission_type);
401 ret = rdb_begin(&p_db, RDB_TRANSACTION_EXCLUSIVE);
402 if(ret != PC_OPERATION_SUCCESS) goto finish;
404 ret = get_app_id_internal(p_db, &i_app_id, s_app_label_name);
405 if(ret != PC_OPERATION_SUCCESS) goto finish;
407 for(i = 0; pp_permissions_list[i] != NULL ; ++i) {
408 // Ignore empty lines
409 if(strspn(pp_permissions_list[i], " \t\n")
410 == strlen(pp_permissions_list[i]))
413 ret = base_name_from_perm(pp_permissions_list[i], &s_permission_name);
414 if(ret != PC_OPERATION_SUCCESS) goto finish;
416 ret = switch_app_permission_internal(p_db,
419 s_permission_group_type_name,
421 free(s_permission_name);
422 if(ret != PC_OPERATION_SUCCESS) goto finish;
425 ret = add_modified_label_internal(p_db, s_app_label_name);
428 return rdb_finish(p_db, ret);
432 int rdb_revoke_app_permissions(const char *const s_app_label_name)
434 RDB_LOG_ENTRY_PARAM("%s", s_app_label_name);
436 int ret = PC_ERR_DB_OPERATION;
437 sqlite3 *p_db = NULL;
439 ret = rdb_begin(&p_db, RDB_TRANSACTION_EXCLUSIVE);
440 if(ret != PC_OPERATION_SUCCESS) goto finish;
442 ret = add_modified_label_internal(p_db, s_app_label_name);
443 if(ret != PC_OPERATION_SUCCESS) goto finish;
445 ret = add_modified_apps_path_internal(p_db, s_app_label_name);
446 if(ret != PC_OPERATION_SUCCESS) goto finish;
448 ret = revoke_app_permissions_internal(p_db, s_app_label_name);
451 return rdb_finish(p_db, ret);
455 int rdb_reset_app_permissions(const char *const s_app_label_name)
457 RDB_LOG_ENTRY_PARAM("%s", s_app_label_name);
459 int ret = PC_ERR_DB_OPERATION;
460 sqlite3 *p_db = NULL;
462 ret = rdb_begin(&p_db, RDB_TRANSACTION_EXCLUSIVE);
463 if(ret != PC_OPERATION_SUCCESS) goto finish;
465 ret = reset_app_permissions_internal(p_db, s_app_label_name);
466 if(ret != PC_OPERATION_SUCCESS) goto finish;
468 ret = add_modified_label_internal(p_db, s_app_label_name);
471 return rdb_finish(p_db, ret);
475 int rdb_add_additional_rules(const char *const *const pp_smack_rules)
479 int ret = PC_ERR_DB_OPERATION;
480 sqlite3 *p_db = NULL;
482 ret = rdb_begin(&p_db, RDB_TRANSACTION_EXCLUSIVE);
483 if(ret != PC_OPERATION_SUCCESS) goto finish;
485 // Old rules may disappear, so mark as modified
486 ret = add_modified_additional_rules_internal(p_db);
487 if(ret != PC_OPERATION_SUCCESS) goto finish;
489 ret = add_additional_rules_internal(p_db, pp_smack_rules);
490 if(ret != PC_OPERATION_SUCCESS) goto finish;
492 // New rules appear, so also mark as modified
493 ret = add_modified_additional_rules_internal(p_db);
496 return rdb_finish(p_db, ret);
499 int rdb_app_has_permission(const char *const s_app_label_name,
500 const char *const s_permission_type_name,
501 const char *const s_permission_name,
502 bool *const p_is_enabled)
504 RDB_LOG_ENTRY_PARAM("%s %s %s", s_app_label_name,
505 s_permission_type_name, s_permission_name);
506 int ret = PC_ERR_DB_OPERATION;
507 sqlite3 *p_db = NULL;
509 ret = rdb_begin(&p_db, RDB_TRANSACTION_SHARED_READ); //shared readonly transaction
510 if(ret != PC_OPERATION_SUCCESS) goto finish;
512 ret = check_app_has_permission_internal(p_db,
515 s_permission_type_name,
519 return rdb_finish(p_db, ret);