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;
36 static bool b_shared_transaction__ = false;
39 RDB_TRANSACTION_EXCLUSIVE,
40 RDB_TRANSACTION_SHARED_READ
41 } rdb_transaction_type_t;
44 * Prepare to modify the database.
46 * @ingroup RDB internal functions
48 * @param pp_db pointer to a pointer to a SQLite3 database object
49 * @param transaction_type indicates whether the transaction is exclusive or shared
50 * @return PC_OPERATION_SUCCESS on success, error code otherwise
52 static int rdb_begin(sqlite3 **pp_db, rdb_transaction_type_t transaction_type)
56 // If rdb_modification_start was called we use a global connection.
57 // Since global connection is always opened only for exclusive transactions, temporary
58 // tables are already created and b_shared_transaction is set to false.
61 return PC_OPERATION_SUCCESS;
64 // Shared transaction doesn't need temporary tables because SMACK labels won't be modified.
65 bool b_create_temporary_tables = transaction_type != RDB_TRANSACTION_SHARED_READ;
66 int ret = open_rdb_connection(pp_db, b_create_temporary_tables);
67 if(ret != PC_OPERATION_SUCCESS) return ret;
69 if(transaction_type == RDB_TRANSACTION_EXCLUSIVE) {
70 b_shared_transaction__ = false;
71 ret = sqlite3_exec(*pp_db, "BEGIN EXCLUSIVE TRANSACTION", 0, 0, 0);
73 else if(transaction_type == RDB_TRANSACTION_SHARED_READ) {
74 b_shared_transaction__ = true;
75 ret = sqlite3_exec(*pp_db, "BEGIN DEFERRED TRANSACTION", 0, 0, 0);
78 C_LOGE("RDB: Bad transaction type specified: %d",
79 (int)transaction_type);
80 return PC_ERR_INVALID_PARAM;
83 if(ret != SQLITE_OK) {
84 C_LOGE("RDB: Error during transaction begin: %s",
85 sqlite3_errmsg(*pp_db));
86 b_shared_transaction__ = false;
87 return PC_ERR_DB_CONNECTION;
95 * Commit database modification.
96 * If previous operation returned an error try to rollback changes.
98 * @ingroup RDB internal functions
100 * @param p_db pointer to a SQLite3 database object
101 * @param i_session_ret session return code
102 * @return PC_OPERATION_SUCCESS on success,
103 * error code otherwise
105 static int rdb_end(sqlite3 *p_db, int i_session_ret)
109 int ret = PC_OPERATION_SUCCESS;
111 // No error during the session, make updates
112 if(i_session_ret == PC_OPERATION_SUCCESS && !b_shared_transaction__) {
113 ret = update_rules_in_db(p_db);
114 if(ret != PC_OPERATION_SUCCESS) {
115 C_LOGE("RDB: Error during updating rules in the database: %d", ret);
120 ret = update_smack_rules(p_db);
121 if(ret != PC_OPERATION_SUCCESS) {
122 C_LOGE("RDB: Error updating smack rules: %d", ret);
129 // End transaction in a way
130 // that depends on the ret and i_session_ret code.
131 if(i_session_ret == PC_OPERATION_SUCCESS &&
132 ret == PC_OPERATION_SUCCESS) {
133 if(sqlite3_exec(p_db, "COMMIT TRANSACTION", 0, 0, 0)
135 C_LOGE("RDB: Error during transaction commit: %s",
136 sqlite3_errmsg(p_db));
137 ret = PC_ERR_DB_CONNECTION;
140 } else if(i_session_ret == PC_ERR_DB_CONNECTION ||
141 ret == PC_ERR_DB_CONNECTION) {
142 // Life is pointless. I can't even rollback...
143 C_LOGE("RDB: No rollback nor commit.");
144 ret = PC_ERR_DB_CONNECTION;
147 // Some other error code
148 if(sqlite3_exec(p_db, "ROLLBACK TRANSACTION", 0, 0, 0)
150 C_LOGE("RDB: Error during transaction rollback: %s",
151 sqlite3_errmsg(p_db));
152 if(ret == PC_OPERATION_SUCCESS)
153 ret = PC_ERR_DB_CONNECTION;
157 if(sqlite3_close(p_db)) {
158 C_LOGE("RDB: Error during closing the database. Error: %s",
159 sqlite3_errmsg(p_db));
160 if(ret == PC_OPERATION_SUCCESS)
161 ret = PC_ERR_DB_CONNECTION;
168 * Finish database modification.
169 * If global transaction is opened update session return code,
170 * otherwise end the transaction.
172 * @ingroup RDB internal functions
174 * @param p_db pointer to a SQLite3 database object
175 * @param i_session_ret session return code
176 * @return PC_OPERATION_SUCCESS on success,
177 * error code otherwise
179 static int rdb_finish(sqlite3 *p_db, int i_session_ret)
182 if(i_session_ret_code__ == PC_OPERATION_SUCCESS)
183 i_session_ret_code__ = i_session_ret;
184 return i_session_ret;
186 int ret = rdb_end(p_db, i_session_ret);
187 return i_session_ret != PC_OPERATION_SUCCESS ? i_session_ret : ret;
192 int rdb_modification_start(void)
195 // We have to finish the previous session:
196 C_LOGW("RDB: rdb_modification_finish was not called!");
197 rdb_modification_finish();
200 return rdb_begin(&p_db__, RDB_TRANSACTION_EXCLUSIVE);
204 int rdb_modification_finish(void)
207 int ret = rdb_end(p_db__, i_session_ret_code__);
209 i_session_ret_code__ = PC_OPERATION_SUCCESS;
212 return PC_OPERATION_SUCCESS;
216 int rdb_modification_rollback(void)
219 if(i_session_ret_code__ == PC_OPERATION_SUCCESS) {
221 i_session_ret_code__ = PC_ERR_INVALID_OPERATION;
223 return rdb_modification_finish();
225 C_LOGE("RDB: Error nothing to rollback");
226 return PC_ERR_INVALID_OPERATION;
230 int rdb_add_application(const char *const s_label_name)
232 RDB_LOG_ENTRY_PARAM("%s", s_label_name);
234 int ret = PC_ERR_DB_OPERATION;
235 sqlite3 *p_db = NULL;
237 ret = rdb_begin(&p_db, RDB_TRANSACTION_EXCLUSIVE);
238 if(ret != PC_OPERATION_SUCCESS) goto finish;
240 ret = check_app_label_internal(p_db, s_label_name);
241 if(ret == PC_ERR_DB_LABEL_TAKEN) {
242 ret = PC_OPERATION_SUCCESS;
243 C_LOGW("RDB: There is an application with label: %s", s_label_name);
245 } else if(ret == PC_OPERATION_SUCCESS) {
246 // There is no such label yet.
247 ret = add_app_internal(p_db, s_label_name);
248 if(ret != PC_OPERATION_SUCCESS) goto finish;
251 ret = add_modified_label_internal(p_db, s_label_name);
254 return rdb_finish(p_db, ret);
258 int rdb_remove_application(const char *const s_label_name)
260 RDB_LOG_ENTRY_PARAM("%s", s_label_name);
262 int ret = PC_ERR_DB_OPERATION;
263 sqlite3 *p_db = NULL;
265 ret = rdb_begin(&p_db, RDB_TRANSACTION_EXCLUSIVE);
266 if(ret != PC_OPERATION_SUCCESS) goto finish;
268 ret = add_modified_label_internal(p_db, s_label_name);
269 if(ret != PC_OPERATION_SUCCESS) goto finish;
271 ret = add_modified_apps_path_internal(p_db, s_label_name);
272 if(ret != PC_OPERATION_SUCCESS) goto finish;
274 ret = remove_app_internal(p_db, s_label_name);
277 return rdb_finish(p_db, ret);
281 int rdb_add_path(const char *const s_owner_label_name,
282 const char *const s_path_label_name,
283 const char *const s_path,
284 const char *const s_access,
285 const char *const s_access_reverse,
286 const char *const s_type)
288 RDB_LOG_ENTRY_PARAM("%s %s %s %s %s %s",
289 s_owner_label_name, s_path_label_name,
290 s_path, s_access, s_access_reverse, s_type);
292 int ret = PC_ERR_DB_OPERATION;
293 sqlite3 *p_db = NULL;
295 ret = rdb_begin(&p_db, RDB_TRANSACTION_EXCLUSIVE);
296 if(ret != PC_OPERATION_SUCCESS) goto finish;
298 ret = add_path_internal(p_db,
305 if(ret != PC_OPERATION_SUCCESS) goto finish;
307 ret = add_modified_label_internal(p_db, s_path_label_name);
310 return rdb_finish(p_db, ret);
314 int rdb_add_permission_rules(const char *const s_permission_name,
315 const char *const s_permission_type_name,
316 const char *const *const pp_smack_rules)
318 RDB_LOG_ENTRY_PARAM("%s %s", s_permission_name, s_permission_type_name);
320 int ret = PC_ERR_DB_OPERATION;
321 sqlite3 *p_db = NULL;
322 sqlite3_int64 permission_id = -1;
324 ret = rdb_begin(&p_db, RDB_TRANSACTION_EXCLUSIVE);
325 if(ret != PC_OPERATION_SUCCESS) goto finish;
327 ret = add_permission_internal(p_db,
329 s_permission_type_name);
330 if(ret != PC_OPERATION_SUCCESS) goto finish;
332 ret = get_permission_id_internal(p_db,
334 s_permission_type_name,
336 if(ret != PC_OPERATION_SUCCESS) goto finish;
338 ret = add_modified_permission_internal(p_db, permission_id);
339 if(ret != PC_OPERATION_SUCCESS) goto finish;
341 if(pp_smack_rules != NULL) {
342 ret = add_permission_rules_internal(p_db,
348 return rdb_finish(p_db, ret);
352 int rdb_enable_app_permissions(const char *const s_app_label_name,
353 const app_type_t i_permission_type,
354 const char *const *const pp_permissions_list,
355 const bool b_is_volatile)
357 RDB_LOG_ENTRY_PARAM("%s %d %d", s_app_label_name, i_permission_type, (int)b_is_volatile);
359 int ret = PC_ERR_DB_OPERATION;
360 sqlite3 *p_db = NULL;
361 char *s_permission_name = NULL;
365 const char *s_permission_type_name = app_type_name(i_permission_type);
366 const char *s_permission_group_type_name = app_type_group_name(i_permission_type);
368 ret = rdb_begin(&p_db, RDB_TRANSACTION_EXCLUSIVE);
369 if(ret != PC_OPERATION_SUCCESS) goto finish;
371 ret = get_app_id_internal(p_db, &i_app_id, s_app_label_name);
372 if(ret != PC_OPERATION_SUCCESS) goto finish;
374 // Add permissions specific for the permission type:
375 ret = change_app_permission_internal(p_db,
377 s_permission_type_name,
378 s_permission_type_name,
381 if(ret != PC_OPERATION_SUCCESS) goto finish;
383 // Add permissions from the list:
384 for(i = 0; pp_permissions_list[i] != NULL; ++i) {
385 // Ignore empty lines
386 if(strspn(pp_permissions_list[i], " \t\n")
387 == strlen(pp_permissions_list[i]))
390 ret = base_name_from_perm(pp_permissions_list[i], &s_permission_name);
391 if(ret != PC_OPERATION_SUCCESS) goto finish;
393 ret = change_app_permission_internal(p_db,
396 s_permission_group_type_name,
399 free(s_permission_name);
400 if(ret != PC_OPERATION_SUCCESS) goto finish;
403 ret = add_modified_label_internal(p_db, s_app_label_name);
406 return rdb_finish(p_db, ret);
410 int rdb_disable_app_permissions(const char *const s_app_label_name,
411 const app_type_t i_permission_type,
412 const char *const *const pp_permissions_list)
414 RDB_LOG_ENTRY_PARAM("%s %d", s_app_label_name, i_permission_type);
416 int ret = PC_ERR_DB_OPERATION;
417 sqlite3 *p_db = NULL;
418 char *s_permission_name = NULL;
420 const char *s_permission_group_type_name = app_type_group_name(i_permission_type);
422 ret = rdb_begin(&p_db, RDB_TRANSACTION_EXCLUSIVE);
423 if(ret != PC_OPERATION_SUCCESS) goto finish;
425 ret = get_app_id_internal(p_db, &i_app_id, s_app_label_name);
426 if(ret != PC_OPERATION_SUCCESS) goto finish;
428 for(i = 0; pp_permissions_list[i] != NULL ; ++i) {
429 // Ignore empty lines
430 if(strspn(pp_permissions_list[i], " \t\n")
431 == strlen(pp_permissions_list[i]))
434 ret = base_name_from_perm(pp_permissions_list[i], &s_permission_name);
435 if(ret != PC_OPERATION_SUCCESS) goto finish;
437 ret = switch_app_permission_internal(p_db,
440 s_permission_group_type_name,
442 free(s_permission_name);
443 if(ret != PC_OPERATION_SUCCESS) goto finish;
446 ret = add_modified_label_internal(p_db, s_app_label_name);
449 return rdb_finish(p_db, ret);
453 int rdb_revoke_app_permissions(const char *const s_app_label_name)
455 RDB_LOG_ENTRY_PARAM("%s", s_app_label_name);
457 int ret = PC_ERR_DB_OPERATION;
458 sqlite3 *p_db = NULL;
460 ret = rdb_begin(&p_db, RDB_TRANSACTION_EXCLUSIVE);
461 if(ret != PC_OPERATION_SUCCESS) goto finish;
463 ret = add_modified_label_internal(p_db, s_app_label_name);
464 if(ret != PC_OPERATION_SUCCESS) goto finish;
466 ret = add_modified_apps_path_internal(p_db, s_app_label_name);
467 if(ret != PC_OPERATION_SUCCESS) goto finish;
469 ret = revoke_app_permissions_internal(p_db, s_app_label_name);
472 return rdb_finish(p_db, ret);
476 int rdb_reset_app_permissions(const char *const s_app_label_name)
478 RDB_LOG_ENTRY_PARAM("%s", s_app_label_name);
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 = reset_app_permissions_internal(p_db, s_app_label_name);
487 if(ret != PC_OPERATION_SUCCESS) goto finish;
489 ret = add_modified_label_internal(p_db, s_app_label_name);
492 return rdb_finish(p_db, ret);