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.
23 * @file rules-db-internals.c
24 * @author Jan Olszak (j.olszak@samsung.com)
26 * @brief Definition of internal functions of the rules-db API.
29 #include <errno.h> // For error logging
30 #include <stdarg.h> // For handling multiple arguments
31 #include <stdlib.h> // For free
32 #include <stdio.h> // For file manipulation
33 #include "common.h" // For smack_label_is_valid
34 #include <unistd.h> // For sleep
36 #include "rules-db-internals.h"
39 #define RDB_MAX_QUERY_ATTEMPTS 50
40 #define RDB_TIME_BETWEEN_ATTEMPTS 1 // sec
46 * Helper function. Use on INSERT or DELETE or UPDATE, when not interested in returned value
48 * @ingroup RDB: internal functions
50 * @param p_stmt SQLite3 statement
51 * @return PC_OPERATION_SUCCESS on success, error code otherwise
53 static int step_and_convert_returned_value(sqlite3_stmt *p_stmt)
55 if(sqlite3_step(p_stmt) == SQLITE_DONE) {
56 return PC_OPERATION_SUCCESS;
58 C_LOGE("RDB: Error during stepping: %s",
59 sqlite3_errmsg(sqlite3_db_handle(p_stmt)));
60 return PC_ERR_DB_QUERY_STEP;
64 int add_modified_label_internal(sqlite3 *p_db, const char *const s_label_name)
66 int ret = PC_OPERATION_SUCCESS;
67 sqlite3_stmt *p_stmt = NULL;
68 ret = prepare_stmt(p_db, &p_stmt,
69 "INSERT OR IGNORE INTO modified_label(name) VALUES(%Q)",
71 if(ret != PC_OPERATION_SUCCESS) goto finish;
73 ret = step_and_convert_returned_value(p_stmt);
75 if(sqlite3_finalize(p_stmt) < 0)
76 C_LOGE("RDB: Error during finalizing statement: %s",
77 sqlite3_errmsg(p_db));
82 int add_modified_permission_internal(sqlite3 *p_db, sqlite3_int64 i_permission_id)
84 int ret = PC_OPERATION_SUCCESS;
85 sqlite3_stmt *p_stmt = NULL;
86 ret = prepare_stmt(p_db, &p_stmt,
87 "INSERT OR IGNORE INTO modified_label(name) \
88 SELECT app_permission_view.app_name \
89 FROM app_permission_view \
90 WHERE app_permission_view.permission_id = %d",
92 if(ret != PC_OPERATION_SUCCESS) goto finish;
94 ret = step_and_convert_returned_value(p_stmt);
96 if(sqlite3_finalize(p_stmt) < 0)
97 C_LOGE("RDB: Error during finalizing statement: %s",
98 sqlite3_errmsg(p_db));
103 int add_modified_apps_path_internal(sqlite3 *p_db,
104 const char *const s_app_label_name)
106 int ret = PC_OPERATION_SUCCESS;
107 sqlite3_stmt *p_stmt = NULL;
108 ret = prepare_stmt(p_db, &p_stmt,
109 "INSERT OR IGNORE INTO modified_label(name) \
110 SELECT path_view.path_label_name \
112 WHERE path_view.owner_app_label_name = %Q",
114 if(ret != PC_OPERATION_SUCCESS) goto finish;
116 ret = step_and_convert_returned_value(p_stmt);
118 if(sqlite3_finalize(p_stmt) < 0)
119 C_LOGE("RDB: Error during finalizing statement: %s",
120 sqlite3_errmsg(p_db));
125 * Function called when the target database is busy.
126 * We attempt to access the database every
127 * RDB_TIME_BETWEEN_ATTEMPTS seconds
129 * @param not_used not used
130 * @param i_attempt number of the attempt
131 * @return 0 when stops waiting
134 static int database_busy_handler(void *not_used UNUSED,
137 if(i_attempt > RDB_MAX_QUERY_ATTEMPTS) {
138 // I ain't gonna wait for you forever!
139 C_LOGE("RDB: Database busy for too long.");
142 C_LOGW("RDB: Database busy, waiting");
143 sleep(RDB_TIME_BETWEEN_ATTEMPTS);
148 int open_rdb_connection(sqlite3 **p_db)
155 int ret = sqlite3_open_v2(RDB_PATH,
160 C_LOGE("RDB: Error opening the database: Unable to allocate memory.");
161 return PC_ERR_DB_CONNECTION;
163 if(ret != SQLITE_OK) {
164 C_LOGE("RDB: Error opening the database: %s", sqlite3_errmsg(*p_db));
165 return PC_ERR_DB_CONNECTION;
168 //Register busy handler:
169 if(sqlite3_busy_handler(*p_db, database_busy_handler, NULL) != SQLITE_OK) {
170 C_LOGE("RDB: Error opening the database: %s", sqlite3_errmsg(*p_db));
171 return PC_ERR_DB_CONNECTION;
175 if(sqlite3_enable_load_extension(*p_db, 1)) {
176 C_LOGE("RDB: Error enabling extensions: %s", sqlite3_errmsg(*p_db));
177 return PC_ERR_DB_CONNECTION;
180 if(sqlite3_load_extension(*p_db,
181 "/usr/lib/librules-db-sql-udf.so", 0,
182 &p_err_msg) != SQLITE_OK) {
184 C_LOGE("RDB: Error during loading librules-db-sql-udf.so: %s",
186 sqlite3_free(p_err_msg);
187 return PC_ERR_DB_CONNECTION;
189 sqlite3_free(p_err_msg);
192 // Create the temporary tables:
193 if(sqlite3_exec(*p_db,
194 "PRAGMA foreign_keys = ON; \
195 CREATE TEMPORARY TABLE history_smack_rule( \
196 subject VARCHAR NOT NULL, \
197 object VARCHAR NOT NULL, \
198 access INTEGER NOT NULL); \
200 CREATE TEMPORARY TABLE modified_label( \
201 name VARCHAR NOT NULL, \
204 CREATE TEMPORARY TABLE all_smack_binary_rule_modified( \
205 subject VARCHAR NOT NULL, \
206 object VARCHAR NOT NULL, \
207 access INTEGER NOT NULL); \
209 CREATE TEMPORARY TABLE history_smack_rule_modified( \
210 subject VARCHAR NOT NULL, \
211 object VARCHAR NOT NULL, \
212 access INTEGER NOT NULL); \
214 CREATE TEMPORARY VIEW modified_smack_rules AS \
215 SELECT subject, object, \
216 access_to_str(access_add) AS access_add, \
217 access_to_str(access_del) AS access_del \
219 SELECT subject, object, \
220 s1.access & ~s2.access AS access_add, \
221 s2.access & ~s1.access AS access_del \
222 FROM all_smack_binary_rule_modified AS s1 \
223 INNER JOIN history_smack_rule_modified AS s2 \
224 USING (subject, object) \
225 WHERE s1.access != s2.access \
227 SELECT subject, object, \
228 s1.access AS access_add, \
230 FROM all_smack_binary_rule_modified s1 \
231 LEFT JOIN history_smack_rule_modified s2 \
232 USING (subject, object) \
233 WHERE s2.subject IS NULL AND \
236 SELECT subject, object, \
238 s1.access AS access_del \
239 FROM history_smack_rule_modified s1 \
240 LEFT JOIN all_smack_binary_rule_modified s2 \
241 USING (subject, object) \
242 WHERE s2.subject IS NULL AND \
245 ORDER BY subject, object ASC;",
246 0, 0, 0) != SQLITE_OK) {
247 C_LOGE("RDB: Error during preparing script: %s", sqlite3_errmsg(*p_db));
248 return PC_ERR_DB_OPERATION;
251 return PC_OPERATION_SUCCESS;
255 int prepare_stmt(sqlite3 *p_db,
256 sqlite3_stmt **pp_stmt,
257 const char *const s_sql,
260 int ret = PC_ERR_DB_QUERY_PREP;
261 char *s_query = NULL;
263 va_start(args, s_sql);
265 s_query = sqlite3_vmprintf(s_sql, args);
267 if(s_query == NULL) {
268 C_LOGE("RDB: Error during preparing statement: Unable to allocate enough memory.");
269 ret = PC_ERR_DB_QUERY_PREP;
273 if(sqlite3_prepare_v2(p_db,
278 C_LOGE("RDB: Error during preparing statement: %s", sqlite3_errmsg(p_db));
279 ret = PC_ERR_DB_QUERY_PREP;
283 if(*pp_stmt == NULL) {
284 C_LOGE("RDB: Error during preparing statement: SQL statement is probably empty.");
285 ret = PC_ERR_DB_QUERY_PREP;
289 ret = PC_OPERATION_SUCCESS;
293 sqlite3_free(s_query);
298 int check_app_label_internal(sqlite3 *p_db,
299 const char *const s_label_name)
301 RDB_LOG_ENTRY_PARAM("%s", s_label_name);
303 int ret = PC_ERR_DB_OPERATION;
304 sqlite3_stmt *p_stmt = NULL;
306 ret = prepare_stmt(p_db, &p_stmt,
307 "SELECT COUNT(application_view.name) \
308 FROM application_view \
309 WHERE application_view.name=%Q \
312 if(ret != PC_OPERATION_SUCCESS) goto finish;
314 ret = sqlite3_step(p_stmt);
315 if(ret == SQLITE_ROW) {
316 switch(sqlite3_column_int(p_stmt, RDB_FIRST_COLUMN)) {
317 case 0: ret = PC_OPERATION_SUCCESS; break;
318 case 1: ret = PC_ERR_DB_LABEL_TAKEN; break;
322 C_LOGE("RDB: Error during stepping: %s", sqlite3_errmsg(p_db));
323 ret = PC_ERR_DB_QUERY_STEP;
326 if(sqlite3_finalize(p_stmt) < 0)
327 C_LOGE("RDB: Error during finalizing statement: %s",
328 sqlite3_errmsg(p_db));
333 int check_label_internal(sqlite3 *p_db,
334 const char *const s_label_name)
336 RDB_LOG_ENTRY_PARAM("%s", s_label_name);
338 int ret = PC_ERR_DB_OPERATION;
339 sqlite3_stmt *p_stmt = NULL;
341 ret = prepare_stmt(p_db, &p_stmt,
342 "SELECT COUNT(label.name) \
343 FROM label WHERE name=%Q LIMIT 1",
346 if(ret != PC_OPERATION_SUCCESS) goto finish;
348 ret = sqlite3_step(p_stmt);
349 if(ret == SQLITE_ROW) {
350 switch(sqlite3_column_int(p_stmt, RDB_FIRST_COLUMN)) {
351 case 0: ret = PC_OPERATION_SUCCESS; break;
352 case 1: ret = PC_ERR_DB_LABEL_TAKEN; break;
356 C_LOGE("RDB: Error during stepping: %s", sqlite3_errmsg(p_db));
357 ret = PC_ERR_DB_QUERY_STEP;
361 if(sqlite3_finalize(p_stmt) < 0)
362 C_LOGE("RDB: Error during finalizing statement: %s",
363 sqlite3_errmsg(p_db));
368 int add_app_internal(sqlite3 *p_db,
369 const char *const s_label_name)
371 RDB_LOG_ENTRY_PARAM("%s", s_label_name);
373 int ret = PC_ERR_DB_OPERATION;
374 sqlite3_stmt *p_stmt = NULL;
376 ret = prepare_stmt(p_db, &p_stmt,
377 "INSERT into application_view(name) VALUES(%Q)",
379 if(ret != PC_OPERATION_SUCCESS) goto finish;
381 ret = step_and_convert_returned_value(p_stmt);
383 if(sqlite3_finalize(p_stmt) < 0)
384 C_LOGE("RDB: Error during finalizing statement: %s",
385 sqlite3_errmsg(p_db));
390 int remove_app_internal(sqlite3 *p_db,
391 const char *const s_label_name)
393 RDB_LOG_ENTRY_PARAM("%s", s_label_name);
395 int ret = PC_ERR_DB_OPERATION;
396 sqlite3_stmt *p_stmt = NULL;
398 ret = prepare_stmt(p_db, &p_stmt,
399 "DELETE FROM application_view \
400 WHERE application_view.name=%Q",
403 if(ret != PC_OPERATION_SUCCESS) goto finish;
405 ret = step_and_convert_returned_value(p_stmt);
407 if(sqlite3_finalize(p_stmt) < 0)
408 C_LOGE("RDB: Error during finalizing statement: %s",
409 sqlite3_errmsg(p_db));
414 int add_path_internal(sqlite3 *p_db,
415 const char *const s_owner_label_name,
416 const char *const s_path_label_name,
417 const char *const s_path,
418 const char *const s_access,
419 const char *const s_type)
421 RDB_LOG_ENTRY_PARAM("%s %s %s %s %s",
422 s_owner_label_name, s_path_label_name,
423 s_path, s_access, s_type);
425 int ret = PC_ERR_DB_OPERATION;
426 sqlite3_stmt *p_stmt = NULL;
428 ret = prepare_stmt(p_db, &p_stmt,
429 "INSERT INTO path_view(owner_app_label_name, \
434 VALUES(%Q, %Q, %Q, %Q, %Q);",
435 s_owner_label_name, s_path,
436 s_path_label_name, s_access, s_type);
437 if(ret != PC_OPERATION_SUCCESS) goto finish;
439 ret = step_and_convert_returned_value(p_stmt);
441 if(sqlite3_finalize(p_stmt) < 0)
442 C_LOGE("RDB: Error during finalizing statement: %s",
443 sqlite3_errmsg(p_db));
448 int check_permission_internal(sqlite3 *p_db,
449 const char *const s_permission_name,
450 const char *const s_permission_type_name)
452 RDB_LOG_ENTRY_PARAM("%s %s", s_permission_name, s_permission_type_name);
454 int ret = PC_ERR_DB_OPERATION;
455 sqlite3_stmt *p_stmt = NULL;
457 ret = prepare_stmt(p_db, &p_stmt,
458 "SELECT COUNT(SELECT permission_view.permission_id \
459 FROM permission_view \
463 s_permission_name, s_permission_type_name);
465 if(ret != PC_OPERATION_SUCCESS) goto finish;
467 ret = sqlite3_step(p_stmt);
468 if(ret == SQLITE_ROW) {
469 switch(sqlite3_column_int(p_stmt, RDB_FIRST_COLUMN)) {
470 case 0: ret = PC_OPERATION_SUCCESS; break; // No such permission
471 case 1: ret = PC_PERMISSION_EXISTS; break; // Permission exists
475 C_LOGE("RDB: Error during stepping: %s", sqlite3_errmsg(p_db));
476 ret = PC_ERR_DB_QUERY_STEP;
480 if(sqlite3_finalize(p_stmt) < 0)
481 C_LOGE("RDB: Error during finalizing statement: %s",
482 sqlite3_errmsg(p_db));
487 int add_permission_internal(sqlite3 *p_db,
488 const char *const s_permission_name,
489 const char *const s_permission_type_name)
491 RDB_LOG_ENTRY_PARAM("%s %s", s_permission_name, s_permission_type_name);
493 int ret = PC_ERR_DB_OPERATION;
494 sqlite3_stmt *p_stmt = NULL;
496 ret = prepare_stmt(p_db, &p_stmt,
497 "INSERT INTO permission_view(name, type_name) \
499 s_permission_name, s_permission_type_name);
501 if(ret != PC_OPERATION_SUCCESS) goto finish;
503 ret = step_and_convert_returned_value(p_stmt);
505 if(sqlite3_finalize(p_stmt) < 0)
506 C_LOGE("RDB: Error during finalizing statement: %s",
507 sqlite3_errmsg(p_db));
512 int get_permission_id_internal(sqlite3 *p_db,
513 const char *const s_permission_name,
514 const char *const s_permission_type_name,
515 sqlite3_int64 *p_permission_id)
517 RDB_LOG_ENTRY_PARAM("%s %s", s_permission_name, s_permission_type_name);
519 int ret = PC_ERR_DB_OPERATION;
520 sqlite3_stmt *p_stmt = NULL;
522 ret = prepare_stmt(p_db, &p_stmt,
523 "SELECT permission_view.permission_id \
524 FROM permission_view \
525 WHERE permission_view.name = %Q AND \
526 permission_view.type_name = %Q \
528 s_permission_name, s_permission_type_name);
529 if(ret != PC_OPERATION_SUCCESS) goto finish;
531 ret = sqlite3_step(p_stmt);
532 if(ret == SQLITE_ROW) {
533 ret = PC_OPERATION_SUCCESS;
534 *p_permission_id = sqlite3_column_int(p_stmt, RDB_FIRST_COLUMN);
535 } else if(ret == SQLITE_DONE) {
536 C_LOGW("RDB: There is no permission_id for %s %s", s_permission_name, s_permission_type_name);
537 ret = PC_ERR_DB_OPERATION;
540 C_LOGE("RDB: Error during stepping: %s", sqlite3_errmsg(p_db));
541 ret = PC_ERR_DB_QUERY_STEP;
545 if(sqlite3_finalize(p_stmt) < 0)
546 C_LOGE("RDB: Error during finalizing statement: %s",
547 sqlite3_errmsg(p_db));
553 int parse_rule(const char *const s_rule,
558 int ret = PC_OPERATION_SUCCESS;
559 char *tmp_s_rule = NULL;
560 const char *tmp_s_subject = NULL;
561 const char *tmp_s_object = NULL;
562 const char *tmp_s_access = NULL;
563 char *saveptr = NULL;
565 // Parse subject, object and access:
566 tmp_s_rule = strdup(s_rule);
567 tmp_s_subject = strtok_r(tmp_s_rule, " \t\n", &saveptr);
568 tmp_s_object = strtok_r(NULL, " \t\n", &saveptr);
569 tmp_s_access = strtok_r(NULL, " \t\n", &saveptr);
571 // Check rule validity:
572 if(tmp_s_subject == NULL ||
573 tmp_s_object == NULL ||
574 tmp_s_access == NULL ||
575 strtok_r(NULL, " \t\n", &saveptr) != NULL) {
576 C_LOGE("RDB: Incorrect rule format: %s", s_rule);
577 ret = PC_ERR_INVALID_PARAM;
582 strcpy(s_subject, tmp_s_subject);
583 strcpy(s_object, tmp_s_object);
584 strcpy(s_access, tmp_s_access);
586 if(tmp_s_rule) free(tmp_s_rule);
591 int add_permission_rules_internal(sqlite3 *p_db,
592 sqlite3_int64 permission_id,
593 const char *const *const pp_smack_rules)
598 int ret = PC_OPERATION_SUCCESS;
599 sqlite3_stmt *p_stmt = NULL;
600 char s_subject[SMACK_LABEL_LEN + 1];
601 char s_object[SMACK_LABEL_LEN + 1];
602 char s_access[ACC_LEN + 1];
604 // Prepare statement.
605 const char *s_query = "INSERT INTO \
606 permission_label_rule_view(permission_id,access,label_name,is_reverse) \
608 if(sqlite3_prepare_v2(p_db,
613 C_LOGE("RDB: Error during preparing statement: %s",
614 sqlite3_errmsg(p_db));
615 ret = PC_ERR_DB_QUERY_PREP;
619 for(i = 0; pp_smack_rules[i] != NULL ; ++i) {
620 C_LOGD("RDB: Granting permission: %s", pp_smack_rules[i]);
622 // Ignore empty lines
623 if(strspn(pp_smack_rules[i], " \t\n") == strlen(pp_smack_rules[i]))
626 ret = parse_rule(pp_smack_rules[i], s_subject, s_object, s_access);
627 if(ret != PC_OPERATION_SUCCESS) goto finish;
629 // Bind values to the statement and run it:
630 sqlite3_bind_int(p_stmt, 1, permission_id);
631 sqlite3_bind_text(p_stmt, 2, s_access, RDB_AUTO_DETERM_SIZE, 0);
632 if(!strcmp(s_subject, SMACK_APP_LABEL_TEMPLATE)) {
634 sqlite3_bind_text(p_stmt, 3, s_object, RDB_AUTO_DETERM_SIZE, 0);
635 sqlite3_bind_int(p_stmt, 4, 0);
637 } else if(!strcmp(s_object, SMACK_APP_LABEL_TEMPLATE)) {
638 sqlite3_bind_text(p_stmt, 3, s_subject, RDB_AUTO_DETERM_SIZE, 0);
639 sqlite3_bind_int(p_stmt, 4, 1);
642 C_LOGE("RDB: Incorrect rule format: %s", pp_smack_rules[i]);
643 ret = PC_ERR_INVALID_PARAM;
647 // Perform the insert
648 ret = step_and_convert_returned_value(p_stmt);
649 if(ret != PC_OPERATION_SUCCESS) goto finish;
651 // Reset and unbind statement:
652 if(sqlite3_reset(p_stmt) != SQLITE_OK) {
653 C_LOGE("RDB: Error reseting statement: %s",
654 sqlite3_errmsg(p_db));
655 ret = PC_ERR_DB_QUERY_STEP;
658 if(sqlite3_clear_bindings(p_stmt) != SQLITE_OK) {
659 C_LOGE("RDB: Error reseting statement: %s",
660 sqlite3_errmsg(p_db));
661 ret = PC_ERR_DB_QUERY_STEP;
667 if(sqlite3_finalize(p_stmt) < 0)
668 C_LOGE("RDB: Error during finalizing statement: %s",
669 sqlite3_errmsg(p_db));
674 int get_app_id_internal(sqlite3 *p_db,
676 const char *const s_app_label_name)
678 RDB_LOG_ENTRY_PARAM("%s", s_app_label_name);
680 int ret = PC_ERR_DB_OPERATION;
681 sqlite3_stmt *p_stmt = NULL;
683 ret = prepare_stmt(p_db, &p_stmt,
684 "SELECT application_view.app_id \
685 FROM application_view \
686 WHERE application_view.name = %Q",
689 if(ret != PC_OPERATION_SUCCESS) goto finish;
691 ret = sqlite3_step(p_stmt);
692 if(ret == SQLITE_ROW) {
693 ret = PC_OPERATION_SUCCESS;
694 *pi_app_id = sqlite3_column_int(p_stmt, RDB_FIRST_COLUMN);
696 } else if(ret == SQLITE_DONE) {
697 C_LOGW("RDB: There is no app_id for %s", s_app_label_name);
698 ret = PC_ERR_DB_OPERATION;
701 C_LOGE("RDB: Error during stepping: %s", sqlite3_errmsg(p_db));
702 ret = PC_ERR_DB_QUERY_STEP;
706 if(sqlite3_finalize(p_stmt) < 0)
707 C_LOGE("RDB: Error during finalizing statement: %s",
708 sqlite3_errmsg(p_db));
713 int add_app_permission_internal(sqlite3 *p_db,
715 const char *const s_permission_name,
716 const char *const s_permission_type_name,
717 const bool b_is_volatile_new,
718 const bool b_is_enabled_new)
720 RDB_LOG_ENTRY_PARAM("%d %s %s %d %d", i_app_id,
721 s_permission_name, s_permission_type_name,
722 b_is_volatile_new, b_is_enabled_new);
725 int ret = PC_ERR_DB_OPERATION;
726 sqlite3_stmt *p_stmt = NULL;
728 ret = prepare_stmt(p_db, &p_stmt,
730 app_permission_view(app_id, name, type_name, \
731 is_volatile, is_enabled) \
732 VALUES(%d,%Q,%Q,%d,%d)",
733 i_app_id, s_permission_name, s_permission_type_name,
734 (int)b_is_volatile_new, (int)b_is_enabled_new);
736 if(ret != PC_OPERATION_SUCCESS) goto finish;
738 ret = step_and_convert_returned_value(p_stmt);
740 if(sqlite3_finalize(p_stmt) < 0)
741 C_LOGE("RDB: Error during finalizing statement: %s",
742 sqlite3_errmsg(p_db));
747 int switch_app_permission_internal(sqlite3 *p_db,
749 const char *const s_permission_name,
750 const char *const s_permission_type_name,
751 const bool b_is_enabled_new)
753 RDB_LOG_ENTRY_PARAM("%d %s %s %d", i_app_id,
754 s_permission_name, s_permission_type_name,
757 int ret = PC_ERR_DB_OPERATION;
758 sqlite3_stmt *p_stmt = NULL;
760 ret = prepare_stmt(p_db, &p_stmt,
761 "UPDATE app_permission_view \
763 WHERE app_id = %d AND \
766 b_is_enabled_new, i_app_id,
767 s_permission_name, s_permission_type_name);
769 if(ret != PC_OPERATION_SUCCESS) goto finish;
770 ret = step_and_convert_returned_value(p_stmt);
772 if(sqlite3_finalize(p_stmt) < 0)
773 C_LOGE("RDB: Error during finalizing statement: %s",
774 sqlite3_errmsg(p_db));
779 int update_app_permission_internal(sqlite3 *p_db,
781 const int i_permission_id,
782 const bool b_is_volatile_new,
783 const bool b_is_enabled_new)
785 RDB_LOG_ENTRY_PARAM("%d %d %d %d",
786 i_app_id, i_permission_id,
787 b_is_volatile_new, b_is_enabled_new);
789 int ret = PC_ERR_DB_OPERATION;
790 sqlite3_stmt *p_stmt = NULL;
792 ret = prepare_stmt(p_db, &p_stmt,
793 "UPDATE app_permission \
794 SET is_volatile = %d, is_enabled=%d \
795 WHERE app_id = %d AND permission_id = %d",
796 b_is_volatile_new, b_is_enabled_new,
797 i_app_id, i_permission_id);
799 if(ret != PC_OPERATION_SUCCESS) goto finish;
800 ret = step_and_convert_returned_value(p_stmt);
802 if(sqlite3_finalize(p_stmt) < 0)
803 C_LOGE("RDB: Error during finalizing statement: %s",
804 sqlite3_errmsg(p_db));
809 int change_app_permission_internal(sqlite3 *p_db,
811 const char *const s_permission_name,
812 const char *const s_permission_type_name,
813 int i_is_volatile_new,
814 int i_is_enabled_new)
816 RDB_LOG_ENTRY_PARAM("%d %s %s %d %d", i_app_id,
817 s_permission_name, s_permission_type_name,
818 i_is_volatile_new, i_is_enabled_new);
820 int ret = PC_ERR_DB_OPERATION;
821 sqlite3_stmt *p_stmt = NULL;
822 int i_is_volatile_old, i_is_enabled_old, i_permission_id;
824 ret = prepare_stmt(p_db, &p_stmt,
825 "SELECT is_volatile, is_enabled, permission_id \
826 FROM app_permission_list_view \
827 WHERE app_id = %d AND \
828 permission_name=%Q AND \
829 permission_type_name=%Q LIMIT 1",
830 i_app_id, s_permission_name, s_permission_type_name);
831 if(ret != PC_OPERATION_SUCCESS) goto finish;
833 ret = sqlite3_step(p_stmt);
834 if(ret == SQLITE_ROW) {
835 // Phi, I already have this permission...
836 i_is_volatile_old = sqlite3_column_int(p_stmt, RDB_FIRST_COLUMN);
837 i_is_enabled_old = sqlite3_column_int(p_stmt, RDB_SECOND_COLUMN);
839 if(i_is_volatile_old == 1 && i_is_volatile_new == 0) {
840 // Confucius say, No man can down-cast volatility.
841 C_LOGE("RDB: Down-casting volatility is forbidden.");
842 ret = PC_ERR_DB_PERM_FORBIDDEN;
846 if(i_is_volatile_old == i_is_volatile_new &&
847 i_is_enabled_old == i_is_enabled_new) {
848 // There is no change. Nice.
849 C_LOGD("RDB: Permission %s %s already exists.", s_permission_name, s_permission_type_name);
850 ret = PC_OPERATION_SUCCESS;
854 i_permission_id = sqlite3_column_int(p_stmt, RDB_THIRD_COLUMN);
856 // Finalize statement
857 if(sqlite3_finalize(p_stmt) < 0)
858 C_LOGE("RDB: Error during finalizing statement: %s",
859 sqlite3_errmsg(p_db));
862 C_LOGD("RDB: Updating permission %s %s to application.", s_permission_name, s_permission_type_name);
863 ret = update_app_permission_internal(p_db,
869 } else if(ret == SQLITE_DONE) {
870 // Wow! A brand new permission! Omnomnom...
872 if(sqlite3_finalize(p_stmt) < 0)
873 C_LOGE("RDB: Error during finalizing statement: %s",
874 sqlite3_errmsg(p_db));
877 C_LOGD("RDB: Adding permission %s %s to application.", s_permission_name, s_permission_type_name);
878 ret = add_app_permission_internal(p_db,
881 s_permission_type_name,
885 C_LOGE("RDB: Error during stepping: %s", sqlite3_errmsg(p_db));
886 ret = PC_ERR_DB_QUERY_STEP;
890 if(p_stmt && sqlite3_finalize(p_stmt) < 0)
891 C_LOGE("RDB: Error during finalizing statement: %s",
892 sqlite3_errmsg(p_db));
897 int revoke_app_permissions_internal(sqlite3 *p_db,
898 const char *const s_app_label_name)
900 RDB_LOG_ENTRY_PARAM("%s", s_app_label_name);
902 int ret = PC_ERR_DB_OPERATION;
903 sqlite3_stmt *p_stmt = NULL;
905 ret = prepare_stmt(p_db, &p_stmt,
906 "DELETE FROM app_permission_view \
907 WHERE app_permission_view.app_name=%Q;",
910 if(ret != PC_OPERATION_SUCCESS) goto finish;
912 ret = step_and_convert_returned_value(p_stmt);
914 if(sqlite3_finalize(p_stmt) < 0)
915 C_LOGE("RDB: Error during finalizing statement: %s",
916 sqlite3_errmsg(p_db));
921 int reset_app_permissions_internal(sqlite3 *p_db,
922 const char *const s_app_label_name)
924 RDB_LOG_ENTRY_PARAM("%s", s_app_label_name);
926 int ret = PC_ERR_DB_OPERATION;
927 sqlite3_stmt *p_stmt = NULL;
929 ret = prepare_stmt(p_db, &p_stmt,
930 "DELETE FROM app_permission_volatile_view \
931 WHERE app_permission_volatile_view.app_name=%Q;",
934 if(ret != PC_OPERATION_SUCCESS) goto finish;
936 ret = step_and_convert_returned_value(p_stmt);
938 if(sqlite3_finalize(p_stmt) < 0)
939 C_LOGE("RDB: Error during finalizing statement: %s",
940 sqlite3_errmsg(p_db));
945 int save_smack_rules(sqlite3 *p_db)
949 if(sqlite3_exec(p_db,
950 "DELETE FROM history_smack_rule; \
952 INSERT INTO history_smack_rule \
953 SELECT subject, object, access \
954 FROM all_smack_binary_rules; \
956 CREATE INDEX history_smack_rule_subject_object_index \
957 ON history_smack_rule(subject, object);",
958 0, 0, 0) != SQLITE_OK) {
959 C_LOGE("RDB: Error during saving history table: %s",
960 sqlite3_errmsg(p_db));
961 return PC_ERR_DB_OPERATION;
964 return PC_OPERATION_SUCCESS;
968 int update_rules_in_db(sqlite3 *p_db)
972 // All rules generated by the present state of the database
973 if(sqlite3_exec(p_db,
974 "DELETE FROM all_smack_binary_rules; \
976 INSERT INTO all_smack_binary_rules \
977 SELECT subject, object, access, is_volatile \
978 FROM all_smack_binary_rules_view; \
980 DELETE FROM all_smack_binary_rule_modified; \
982 INSERT INTO all_smack_binary_rule_modified \
983 SELECT subject, object, access \
984 FROM all_smack_binary_rules, \
986 WHERE subject IN modified_label OR \
987 object IN modified_label; \
989 DELETE FROM history_smack_rule_modified; \
991 INSERT INTO history_smack_rule_modified \
992 SELECT subject, object, access \
993 FROM history_smack_rule, \
995 WHERE subject IN modified_label OR \
996 object IN modified_label; \
998 0, 0, 0) != SQLITE_OK) {
999 C_LOGE("RDB: Error during updating rules: %s",
1000 sqlite3_errmsg(p_db));
1001 return PC_ERR_DB_OPERATION;
1003 return PC_OPERATION_SUCCESS;
1006 int update_smack_rules(sqlite3 *p_db)
1010 int ret = PC_OPERATION_SUCCESS;
1011 sqlite3_stmt *p_stmt = NULL;
1012 const unsigned char *s_subject = NULL;
1013 const unsigned char *s_object = NULL;
1014 const unsigned char *s_access_add = NULL;
1015 const unsigned char *s_access_del = NULL;
1016 struct smack_accesses *smack = NULL;
1018 if(smack_accesses_new(&smack)) {
1019 C_LOGE("RDB: Error during updating smack rules: smack_accesses_new failed.");
1020 ret = PC_ERR_MEM_OPERATION;
1024 ret = prepare_stmt(p_db, &p_stmt,
1025 "SELECT * from modified_smack_rules;");
1026 if(ret != PC_OPERATION_SUCCESS) goto finish;
1028 while((ret = sqlite3_step(p_stmt)) == SQLITE_ROW) {
1029 s_subject = sqlite3_column_text(p_stmt, RDB_FIRST_COLUMN);
1030 s_object = sqlite3_column_text(p_stmt, RDB_SECOND_COLUMN);
1031 s_access_add = sqlite3_column_text(p_stmt, RDB_THIRD_COLUMN);
1032 s_access_del = sqlite3_column_text(p_stmt, RDB_FOURTH_COLUMN);
1034 C_LOGD("RDB: Added rule to smack:: %s %s %s %s",
1035 s_subject, s_object, s_access_add, s_access_del);
1037 if(smack_accesses_add_modify(smack,
1038 (const char *) s_subject,
1039 (const char *) s_object,
1040 (const char *) s_access_add,
1041 (const char *) s_access_del)) {
1042 C_LOGE("RDB: Error during updating smack rules: %s",
1043 sqlite3_errmsg(p_db));
1044 ret = PC_ERR_INVALID_OPERATION;
1048 if(ret == SQLITE_DONE) {
1049 ret = PC_OPERATION_SUCCESS;
1051 C_LOGE("RDB: Error during updating smack rules [%d]: %s",
1052 ret, sqlite3_errmsg(p_db));
1053 ret = PC_ERR_DB_OPERATION;
1056 if(smack_accesses_apply(smack)) {
1057 C_LOGE("RDB: Error in smack_accesses_apply");
1058 ret = PC_ERR_INVALID_OPERATION;
1062 if(sqlite3_finalize(p_stmt) < 0)
1063 C_LOGE("RDB: Error during finalizing statement: %s",
1064 sqlite3_errmsg(p_db));
1066 smack_accesses_free(smack);