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; \
247 0, 0, 0) != SQLITE_OK) {
248 C_LOGE("RDB: Error during preparing script: %s", sqlite3_errmsg(*p_db));
249 return PC_ERR_DB_OPERATION;
252 return PC_OPERATION_SUCCESS;
256 int prepare_stmt(sqlite3 *p_db,
257 sqlite3_stmt **pp_stmt,
258 const char *const s_sql,
261 int ret = PC_ERR_DB_QUERY_PREP;
262 char *s_query = NULL;
264 va_start(args, s_sql);
266 s_query = sqlite3_vmprintf(s_sql, args);
268 if(s_query == NULL) {
269 C_LOGE("RDB: Error during preparing statement: Unable to allocate enough memory.");
270 ret = PC_ERR_DB_QUERY_PREP;
274 if(sqlite3_prepare_v2(p_db,
279 C_LOGE("RDB: Error during preparing statement: %s", sqlite3_errmsg(p_db));
280 ret = PC_ERR_DB_QUERY_PREP;
284 if(*pp_stmt == NULL) {
285 C_LOGE("RDB: Error during preparing statement: SQL statement is probably empty.");
286 ret = PC_ERR_DB_QUERY_PREP;
290 ret = PC_OPERATION_SUCCESS;
294 sqlite3_free(s_query);
299 int check_app_label_internal(sqlite3 *p_db,
300 const char *const s_label_name)
302 RDB_LOG_ENTRY_PARAM("%s", s_label_name);
304 int ret = PC_ERR_DB_OPERATION;
305 sqlite3_stmt *p_stmt = NULL;
307 ret = prepare_stmt(p_db, &p_stmt,
308 "SELECT COUNT(application_view.name) \
309 FROM application_view \
310 WHERE application_view.name=%Q \
313 if(ret != PC_OPERATION_SUCCESS) goto finish;
315 ret = sqlite3_step(p_stmt);
316 if(ret == SQLITE_ROW) {
317 switch(sqlite3_column_int(p_stmt, RDB_FIRST_COLUMN)) {
318 case 0: ret = PC_OPERATION_SUCCESS; break;
319 case 1: ret = PC_ERR_DB_LABEL_TAKEN; break;
323 C_LOGE("RDB: Error during stepping: %s", sqlite3_errmsg(p_db));
324 ret = PC_ERR_DB_QUERY_STEP;
327 if(sqlite3_finalize(p_stmt) < 0)
328 C_LOGE("RDB: Error during finalizing statement: %s",
329 sqlite3_errmsg(p_db));
334 int check_label_internal(sqlite3 *p_db,
335 const char *const s_label_name)
337 RDB_LOG_ENTRY_PARAM("%s", s_label_name);
339 int ret = PC_ERR_DB_OPERATION;
340 sqlite3_stmt *p_stmt = NULL;
342 ret = prepare_stmt(p_db, &p_stmt,
343 "SELECT COUNT(label.name) \
344 FROM label WHERE name=%Q LIMIT 1",
347 if(ret != PC_OPERATION_SUCCESS) goto finish;
349 ret = sqlite3_step(p_stmt);
350 if(ret == SQLITE_ROW) {
351 switch(sqlite3_column_int(p_stmt, RDB_FIRST_COLUMN)) {
352 case 0: ret = PC_OPERATION_SUCCESS; break;
353 case 1: ret = PC_ERR_DB_LABEL_TAKEN; break;
357 C_LOGE("RDB: Error during stepping: %s", sqlite3_errmsg(p_db));
358 ret = PC_ERR_DB_QUERY_STEP;
362 if(sqlite3_finalize(p_stmt) < 0)
363 C_LOGE("RDB: Error during finalizing statement: %s",
364 sqlite3_errmsg(p_db));
369 int add_app_internal(sqlite3 *p_db,
370 const char *const s_label_name)
372 RDB_LOG_ENTRY_PARAM("%s", s_label_name);
374 int ret = PC_ERR_DB_OPERATION;
375 sqlite3_stmt *p_stmt = NULL;
377 ret = prepare_stmt(p_db, &p_stmt,
378 "INSERT into application_view(name) VALUES(%Q)",
380 if(ret != PC_OPERATION_SUCCESS) goto finish;
382 ret = step_and_convert_returned_value(p_stmt);
384 if(sqlite3_finalize(p_stmt) < 0)
385 C_LOGE("RDB: Error during finalizing statement: %s",
386 sqlite3_errmsg(p_db));
391 int remove_app_internal(sqlite3 *p_db,
392 const char *const s_label_name)
394 RDB_LOG_ENTRY_PARAM("%s", s_label_name);
396 int ret = PC_ERR_DB_OPERATION;
397 sqlite3_stmt *p_stmt = NULL;
399 ret = prepare_stmt(p_db, &p_stmt,
400 "DELETE FROM application_view \
401 WHERE application_view.name=%Q",
404 if(ret != PC_OPERATION_SUCCESS) goto finish;
406 ret = step_and_convert_returned_value(p_stmt);
408 if(sqlite3_finalize(p_stmt) < 0)
409 C_LOGE("RDB: Error during finalizing statement: %s",
410 sqlite3_errmsg(p_db));
415 int add_path_internal(sqlite3 *p_db,
416 const char *const s_owner_label_name,
417 const char *const s_path_label_name,
418 const char *const s_path,
419 const char *const s_access,
420 const char *const s_type)
422 RDB_LOG_ENTRY_PARAM("%s %s %s %s %s",
423 s_owner_label_name, s_path_label_name,
424 s_path, s_access, s_type);
426 int ret = PC_ERR_DB_OPERATION;
427 sqlite3_stmt *p_stmt = NULL;
429 ret = prepare_stmt(p_db, &p_stmt,
430 "INSERT INTO path_view(owner_app_label_name, \
435 VALUES(%Q, %Q, %Q, %Q, %Q);",
436 s_owner_label_name, s_path,
437 s_path_label_name, s_access, s_type);
438 if(ret != PC_OPERATION_SUCCESS) goto finish;
440 ret = step_and_convert_returned_value(p_stmt);
442 if(sqlite3_finalize(p_stmt) < 0)
443 C_LOGE("RDB: Error during finalizing statement: %s",
444 sqlite3_errmsg(p_db));
449 int check_permission_internal(sqlite3 *p_db,
450 const char *const s_permission_name,
451 const char *const s_permission_type_name)
453 RDB_LOG_ENTRY_PARAM("%s %s", s_permission_name, s_permission_type_name);
455 int ret = PC_ERR_DB_OPERATION;
456 sqlite3_stmt *p_stmt = NULL;
458 ret = prepare_stmt(p_db, &p_stmt,
459 "SELECT COUNT(SELECT permission_view.permission_id \
460 FROM permission_view \
464 s_permission_name, s_permission_type_name);
466 if(ret != PC_OPERATION_SUCCESS) goto finish;
468 ret = sqlite3_step(p_stmt);
469 if(ret == SQLITE_ROW) {
470 switch(sqlite3_column_int(p_stmt, RDB_FIRST_COLUMN)) {
471 case 0: ret = PC_OPERATION_SUCCESS; break; // No such permission
472 case 1: ret = PC_PERMISSION_EXISTS; break; // Permission exists
476 C_LOGE("RDB: Error during stepping: %s", sqlite3_errmsg(p_db));
477 ret = PC_ERR_DB_QUERY_STEP;
481 if(sqlite3_finalize(p_stmt) < 0)
482 C_LOGE("RDB: Error during finalizing statement: %s",
483 sqlite3_errmsg(p_db));
488 int add_permission_internal(sqlite3 *p_db,
489 const char *const s_permission_name,
490 const char *const s_permission_type_name)
492 RDB_LOG_ENTRY_PARAM("%s %s", s_permission_name, s_permission_type_name);
494 int ret = PC_ERR_DB_OPERATION;
495 sqlite3_stmt *p_stmt = NULL;
497 ret = prepare_stmt(p_db, &p_stmt,
498 "INSERT INTO permission_view(name, type_name) \
500 s_permission_name, s_permission_type_name);
502 if(ret != PC_OPERATION_SUCCESS) goto finish;
504 ret = step_and_convert_returned_value(p_stmt);
506 if(sqlite3_finalize(p_stmt) < 0)
507 C_LOGE("RDB: Error during finalizing statement: %s",
508 sqlite3_errmsg(p_db));
513 int get_permission_id_internal(sqlite3 *p_db,
514 const char *const s_permission_name,
515 const char *const s_permission_type_name,
516 sqlite3_int64 *p_permission_id)
518 RDB_LOG_ENTRY_PARAM("%s %s", s_permission_name, s_permission_type_name);
520 int ret = PC_ERR_DB_OPERATION;
521 sqlite3_stmt *p_stmt = NULL;
523 ret = prepare_stmt(p_db, &p_stmt,
524 "SELECT permission_view.permission_id \
525 FROM permission_view \
526 WHERE permission_view.name = %Q AND \
527 permission_view.type_name = %Q \
529 s_permission_name, s_permission_type_name);
530 if(ret != PC_OPERATION_SUCCESS) goto finish;
532 ret = sqlite3_step(p_stmt);
533 if(ret == SQLITE_ROW) {
534 ret = PC_OPERATION_SUCCESS;
535 *p_permission_id = sqlite3_column_int(p_stmt, RDB_FIRST_COLUMN);
536 } else if(ret == SQLITE_DONE) {
537 C_LOGW("RDB: There is no permission_id for %s %s", s_permission_name, s_permission_type_name);
538 ret = PC_ERR_DB_OPERATION;
541 C_LOGE("RDB: Error during stepping: %s", sqlite3_errmsg(p_db));
542 ret = PC_ERR_DB_QUERY_STEP;
546 if(sqlite3_finalize(p_stmt) < 0)
547 C_LOGE("RDB: Error during finalizing statement: %s",
548 sqlite3_errmsg(p_db));
554 int parse_rule(const char *const s_rule,
559 int ret = PC_OPERATION_SUCCESS;
560 char *tmp_s_rule = NULL;
561 const char *tmp_s_subject = NULL;
562 const char *tmp_s_object = NULL;
563 const char *tmp_s_access = NULL;
564 char *saveptr = NULL;
566 // Parse subject, object and access:
567 tmp_s_rule = strdup(s_rule);
568 tmp_s_subject = strtok_r(tmp_s_rule, " \t\n", &saveptr);
569 tmp_s_object = strtok_r(NULL, " \t\n", &saveptr);
570 tmp_s_access = strtok_r(NULL, " \t\n", &saveptr);
572 // Check rule validity:
573 if(tmp_s_subject == NULL ||
574 tmp_s_object == NULL ||
575 tmp_s_access == NULL ||
576 strtok_r(NULL, " \t\n", &saveptr) != NULL) {
577 C_LOGE("RDB: Incorrect rule format: %s", s_rule);
578 ret = PC_ERR_INVALID_PARAM;
583 strcpy(s_subject, tmp_s_subject);
584 strcpy(s_object, tmp_s_object);
585 strcpy(s_access, tmp_s_access);
587 if(tmp_s_rule) free(tmp_s_rule);
592 int add_permission_rules_internal(sqlite3 *p_db,
593 sqlite3_int64 permission_id,
594 const char *const *const pp_smack_rules)
599 int ret = PC_OPERATION_SUCCESS;
600 sqlite3_stmt *p_stmt = NULL;
601 char s_subject[SMACK_LABEL_LEN + 1];
602 char s_object[SMACK_LABEL_LEN + 1];
603 char s_access[ACC_LEN + 1];
605 // Prepare statement.
606 const char *s_query = "INSERT INTO \
607 permission_label_rule_view(permission_id,access,label_name,is_reverse) \
609 if(sqlite3_prepare_v2(p_db,
614 C_LOGE("RDB: Error during preparing statement: %s",
615 sqlite3_errmsg(p_db));
616 ret = PC_ERR_DB_QUERY_PREP;
620 for(i = 0; pp_smack_rules[i] != NULL ; ++i) {
621 C_LOGD("RDB: Granting permission: %s", pp_smack_rules[i]);
623 // Ignore empty lines
624 if(strspn(pp_smack_rules[i], " \t\n") == strlen(pp_smack_rules[i]))
627 ret = parse_rule(pp_smack_rules[i], s_subject, s_object, s_access);
628 if(ret != PC_OPERATION_SUCCESS) goto finish;
630 // Bind values to the statement and run it:
631 sqlite3_bind_int(p_stmt, 1, permission_id);
632 sqlite3_bind_text(p_stmt, 2, s_access, RDB_AUTO_DETERM_SIZE, 0);
633 if(!strcmp(s_subject, SMACK_APP_LABEL_TEMPLATE)) {
635 sqlite3_bind_text(p_stmt, 3, s_object, RDB_AUTO_DETERM_SIZE, 0);
636 sqlite3_bind_int(p_stmt, 4, 0);
638 } else if(!strcmp(s_object, SMACK_APP_LABEL_TEMPLATE)) {
639 sqlite3_bind_text(p_stmt, 3, s_subject, RDB_AUTO_DETERM_SIZE, 0);
640 sqlite3_bind_int(p_stmt, 4, 1);
643 C_LOGE("RDB: Incorrect rule format: %s", pp_smack_rules[i]);
644 ret = PC_ERR_INVALID_PARAM;
648 // Perform the insert
649 ret = step_and_convert_returned_value(p_stmt);
650 if(ret != PC_OPERATION_SUCCESS) goto finish;
652 // Reset and unbind statement:
653 if(sqlite3_reset(p_stmt) != SQLITE_OK) {
654 C_LOGE("RDB: Error reseting statement: %s",
655 sqlite3_errmsg(p_db));
656 ret = PC_ERR_DB_QUERY_STEP;
659 if(sqlite3_clear_bindings(p_stmt) != SQLITE_OK) {
660 C_LOGE("RDB: Error reseting statement: %s",
661 sqlite3_errmsg(p_db));
662 ret = PC_ERR_DB_QUERY_STEP;
668 if(sqlite3_finalize(p_stmt) < 0)
669 C_LOGE("RDB: Error during finalizing statement: %s",
670 sqlite3_errmsg(p_db));
675 int get_app_id_internal(sqlite3 *p_db,
677 const char *const s_app_label_name)
679 RDB_LOG_ENTRY_PARAM("%s", s_app_label_name);
681 int ret = PC_ERR_DB_OPERATION;
682 sqlite3_stmt *p_stmt = NULL;
684 ret = prepare_stmt(p_db, &p_stmt,
685 "SELECT application_view.app_id \
686 FROM application_view \
687 WHERE application_view.name = %Q",
690 if(ret != PC_OPERATION_SUCCESS) goto finish;
692 ret = sqlite3_step(p_stmt);
693 if(ret == SQLITE_ROW) {
694 ret = PC_OPERATION_SUCCESS;
695 *pi_app_id = sqlite3_column_int(p_stmt, RDB_FIRST_COLUMN);
697 } else if(ret == SQLITE_DONE) {
698 C_LOGW("RDB: There is no app_id for %s", s_app_label_name);
699 ret = PC_ERR_DB_OPERATION;
702 C_LOGE("RDB: Error during stepping: %s", sqlite3_errmsg(p_db));
703 ret = PC_ERR_DB_QUERY_STEP;
707 if(sqlite3_finalize(p_stmt) < 0)
708 C_LOGE("RDB: Error during finalizing statement: %s",
709 sqlite3_errmsg(p_db));
714 int add_app_permission_internal(sqlite3 *p_db,
716 const char *const s_permission_name,
717 const char *const s_permission_type_name,
718 const bool b_is_volatile_new,
719 const bool b_is_enabled_new)
721 RDB_LOG_ENTRY_PARAM("%d %s %s %d %d", i_app_id,
722 s_permission_name, s_permission_type_name,
723 b_is_volatile_new, b_is_enabled_new);
726 int ret = PC_ERR_DB_OPERATION;
727 sqlite3_stmt *p_stmt = NULL;
729 ret = prepare_stmt(p_db, &p_stmt,
731 app_permission_view(app_id, name, type_name, \
732 is_volatile, is_enabled) \
733 VALUES(%d,%Q,%Q,%d,%d)",
734 i_app_id, s_permission_name, s_permission_type_name,
735 (int)b_is_volatile_new, (int)b_is_enabled_new);
737 if(ret != PC_OPERATION_SUCCESS) goto finish;
739 ret = step_and_convert_returned_value(p_stmt);
741 if(sqlite3_finalize(p_stmt) < 0)
742 C_LOGE("RDB: Error during finalizing statement: %s",
743 sqlite3_errmsg(p_db));
748 int switch_app_permission_internal(sqlite3 *p_db,
750 const char *const s_permission_name,
751 const char *const s_permission_type_name,
752 const bool b_is_enabled_new)
754 RDB_LOG_ENTRY_PARAM("%d %s %s %d", i_app_id,
755 s_permission_name, s_permission_type_name,
758 int ret = PC_ERR_DB_OPERATION;
759 sqlite3_stmt *p_stmt = NULL;
761 ret = prepare_stmt(p_db, &p_stmt,
762 "UPDATE app_permission_view \
764 WHERE app_id = %d AND \
767 b_is_enabled_new, i_app_id,
768 s_permission_name, s_permission_type_name);
770 if(ret != PC_OPERATION_SUCCESS) goto finish;
771 ret = step_and_convert_returned_value(p_stmt);
773 if(sqlite3_finalize(p_stmt) < 0)
774 C_LOGE("RDB: Error during finalizing statement: %s",
775 sqlite3_errmsg(p_db));
780 int update_app_permission_internal(sqlite3 *p_db,
782 const int i_permission_id,
783 const bool b_is_volatile_new,
784 const bool b_is_enabled_new)
786 RDB_LOG_ENTRY_PARAM("%d %d %d %d",
787 i_app_id, i_permission_id,
788 b_is_volatile_new, b_is_enabled_new);
790 int ret = PC_ERR_DB_OPERATION;
791 sqlite3_stmt *p_stmt = NULL;
793 ret = prepare_stmt(p_db, &p_stmt,
794 "UPDATE app_permission \
795 SET is_volatile = %d, is_enabled=%d \
796 WHERE app_id = %d AND permission_id = %d",
797 b_is_volatile_new, b_is_enabled_new,
798 i_app_id, i_permission_id);
800 if(ret != PC_OPERATION_SUCCESS) goto finish;
801 ret = step_and_convert_returned_value(p_stmt);
803 if(sqlite3_finalize(p_stmt) < 0)
804 C_LOGE("RDB: Error during finalizing statement: %s",
805 sqlite3_errmsg(p_db));
810 int change_app_permission_internal(sqlite3 *p_db,
812 const char *const s_permission_name,
813 const char *const s_permission_type_name,
814 int i_is_volatile_new,
815 int i_is_enabled_new)
817 RDB_LOG_ENTRY_PARAM("%d %d %d %d %d", i_app_id,
818 s_permission_name, s_permission_type_name,
819 i_is_volatile_new, i_is_enabled_new);
821 int ret = PC_ERR_DB_OPERATION;
822 sqlite3_stmt *p_stmt = NULL;
823 int i_is_volatile_old, i_is_enabled_old, i_permission_id;
825 ret = prepare_stmt(p_db, &p_stmt,
826 "SELECT is_volatile, is_enabled, permission_id \
827 FROM app_permission_list_view \
828 WHERE app_id = %d AND \
829 permission_name=%Q AND \
830 permission_type_name=%Q LIMIT 1",
831 i_app_id, s_permission_name, s_permission_type_name);
832 if(ret != PC_OPERATION_SUCCESS) goto finish;
834 ret = sqlite3_step(p_stmt);
835 if(ret == SQLITE_ROW) {
836 // Phi, I already have this permission...
837 i_is_volatile_old = sqlite3_column_int(p_stmt, RDB_FIRST_COLUMN);
838 i_is_enabled_old = sqlite3_column_int(p_stmt, RDB_SECOND_COLUMN);
840 if(i_is_volatile_old == 1 && i_is_volatile_new == 0) {
841 // Confucius say, No man can down-cast volatility.
842 C_LOGE("RDB: Down-casting volatility is forbidden.");
843 ret = PC_ERR_DB_PERM_FORBIDDEN;
847 if(i_is_volatile_old == i_is_volatile_new &&
848 i_is_enabled_old == i_is_enabled_new) {
849 // There is no change. Nice.
850 C_LOGD("RDB: Permission %s %s already exists.", s_permission_name, s_permission_type_name);
851 ret = PC_OPERATION_SUCCESS;
855 i_permission_id = sqlite3_column_int(p_stmt, RDB_THIRD_COLUMN);
857 // Finalize statement
858 if(sqlite3_finalize(p_stmt) < 0)
859 C_LOGE("RDB: Error during finalizing statement: %s",
860 sqlite3_errmsg(p_db));
863 C_LOGD("RDB: Updating permission %s %s to application.", s_permission_name, s_permission_type_name);
864 ret = update_app_permission_internal(p_db,
870 } else if(ret == SQLITE_DONE) {
871 // Wow! A brand new permission! Omnomnom...
873 if(sqlite3_finalize(p_stmt) < 0)
874 C_LOGE("RDB: Error during finalizing statement: %s",
875 sqlite3_errmsg(p_db));
878 C_LOGD("RDB: Adding permission %s %s to application.", s_permission_name, s_permission_type_name);
879 ret = add_app_permission_internal(p_db,
882 s_permission_type_name,
886 C_LOGE("RDB: Error during stepping: %s", sqlite3_errmsg(p_db));
887 ret = PC_ERR_DB_QUERY_STEP;
891 if(p_stmt && sqlite3_finalize(p_stmt) < 0)
892 C_LOGE("RDB: Error during finalizing statement: %s",
893 sqlite3_errmsg(p_db));
898 int revoke_app_permissions_internal(sqlite3 *p_db,
899 const char *const s_app_label_name)
901 RDB_LOG_ENTRY_PARAM("%s", s_app_label_name);
903 int ret = PC_ERR_DB_OPERATION;
904 sqlite3_stmt *p_stmt = NULL;
906 ret = prepare_stmt(p_db, &p_stmt,
907 "DELETE FROM app_permission_view \
908 WHERE app_permission_view.app_name=%Q;",
911 if(ret != PC_OPERATION_SUCCESS) goto finish;
913 ret = step_and_convert_returned_value(p_stmt);
915 if(sqlite3_finalize(p_stmt) < 0)
916 C_LOGE("RDB: Error during finalizing statement: %s",
917 sqlite3_errmsg(p_db));
922 int reset_app_permissions_internal(sqlite3 *p_db,
923 const char *const s_app_label_name)
925 RDB_LOG_ENTRY_PARAM("%s", s_app_label_name);
927 int ret = PC_ERR_DB_OPERATION;
928 sqlite3_stmt *p_stmt = NULL;
930 ret = prepare_stmt(p_db, &p_stmt,
931 "DELETE FROM app_permission_volatile_view \
932 WHERE app_permission_volatile_view.app_name=%Q;",
935 if(ret != PC_OPERATION_SUCCESS) goto finish;
937 ret = step_and_convert_returned_value(p_stmt);
939 if(sqlite3_finalize(p_stmt) < 0)
940 C_LOGE("RDB: Error during finalizing statement: %s",
941 sqlite3_errmsg(p_db));
946 int save_smack_rules(sqlite3 *p_db)
950 if(sqlite3_exec(p_db,
951 "DELETE FROM history_smack_rule; \
953 INSERT INTO history_smack_rule \
954 SELECT subject, object, access \
955 FROM all_smack_binary_rules; \
957 CREATE INDEX history_smack_rule_subject_object_index \
958 ON history_smack_rule(subject, object);",
959 0, 0, 0) != SQLITE_OK) {
960 C_LOGE("RDB: Error during saving history table: %s",
961 sqlite3_errmsg(p_db));
962 return PC_ERR_DB_OPERATION;
965 return PC_OPERATION_SUCCESS;
969 static int update_rules_in_db(sqlite3 *p_db)
973 // All rules generated by the present state of the database
974 if(sqlite3_exec(p_db,
975 "DELETE FROM all_smack_binary_rules; \
977 INSERT INTO all_smack_binary_rules \
978 SELECT subject, object, access, is_volatile \
979 FROM all_smack_binary_rules_view; \
981 DELETE FROM all_smack_binary_rule_modified; \
983 INSERT INTO all_smack_binary_rule_modified \
984 SELECT subject, object, access \
985 FROM all_smack_binary_rules, \
987 WHERE subject IN modified_label OR \
988 object IN modified_label; \
990 DELETE FROM history_smack_rule_modified; \
992 INSERT INTO history_smack_rule_modified \
993 SELECT subject, object, access \
994 FROM history_smack_rule, \
996 WHERE subject IN modified_label OR \
997 object IN modified_label; \
999 0, 0, 0) != SQLITE_OK) {
1000 C_LOGE("RDB: Error during updating rules: %s",
1001 sqlite3_errmsg(p_db));
1002 return PC_ERR_DB_OPERATION;
1004 return PC_OPERATION_SUCCESS;
1007 int update_smack_rules(sqlite3 *p_db)
1011 int ret = PC_OPERATION_SUCCESS;
1012 sqlite3_stmt *p_stmt = NULL;
1013 const unsigned char *s_subject = NULL;
1014 const unsigned char *s_object = NULL;
1015 const unsigned char *s_access_add = NULL;
1016 const unsigned char *s_access_del = NULL;
1017 struct smack_accesses *smack = NULL;
1019 ret = update_rules_in_db(p_db);
1020 if(ret != PC_OPERATION_SUCCESS) goto finish;
1022 if(smack_accesses_new(&smack)) {
1023 C_LOGE("RDB: Error during updating smack rules: smack_accesses_new failed.");
1024 ret = PC_ERR_MEM_OPERATION;
1028 ret = prepare_stmt(p_db, &p_stmt,
1029 "SELECT * from modified_smack_rules;");
1030 if(ret != PC_OPERATION_SUCCESS) goto finish;
1032 while((ret = sqlite3_step(p_stmt)) == SQLITE_ROW) {
1033 s_subject = sqlite3_column_text(p_stmt, RDB_FIRST_COLUMN);
1034 s_object = sqlite3_column_text(p_stmt, RDB_SECOND_COLUMN);
1035 s_access_add = sqlite3_column_text(p_stmt, RDB_THIRD_COLUMN);
1036 s_access_del = sqlite3_column_text(p_stmt, RDB_FOURTH_COLUMN);
1038 C_LOGD("RDB: Added rule to smack:: %s %s %s %s",
1039 s_subject, s_object, s_access_add, s_access_del);
1041 if(smack_accesses_add_modify(smack,
1042 (const char *) s_subject,
1043 (const char *) s_object,
1044 (const char *) s_access_add,
1045 (const char *) s_access_del)) {
1046 C_LOGE("RDB: Error during updating smack rules: %s",
1047 sqlite3_errmsg(p_db));
1048 ret = PC_ERR_INVALID_OPERATION;
1052 if(ret == SQLITE_DONE) {
1053 ret = PC_OPERATION_SUCCESS;
1055 C_LOGE("RDB: Error during updating smack rules [%d]: %s",
1056 ret, sqlite3_errmsg(p_db));
1057 ret = PC_ERR_DB_OPERATION;
1060 if(smack_accesses_apply(smack)) {
1061 C_LOGE("RDB: Error in smack_accesses_apply");
1062 ret = PC_ERR_INVALID_OPERATION;
1066 if(sqlite3_finalize(p_stmt) < 0)
1067 C_LOGE("RDB: Error during finalizing statement: %s",
1068 sqlite3_errmsg(p_db));
1070 smack_accesses_free(smack);