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));
83 * Adds label names of applications with the permission to modified labels.
84 * Used when permission is going to change and we're going to change some
85 * accesses granted by this permission.
88 * @param p_db [description]
89 * @param i_permission_id [description]
90 * @return [description]
92 int add_modified_permission_internal(sqlite3 *p_db, sqlite3_int64 i_permission_id)
94 int ret = PC_OPERATION_SUCCESS;
95 sqlite3_stmt *p_stmt = NULL;
96 ret = prepare_stmt(p_db, &p_stmt,
97 "INSERT INTO modified_label(name) \
98 SELECT app_permission_view.app_name \
99 FROM app_permission_view \
100 WHERE app_permission_view.permission_id = %d",
102 if(ret != PC_OPERATION_SUCCESS) goto finish;
104 ret = step_and_convert_returned_value(p_stmt);
106 if(sqlite3_finalize(p_stmt) < 0)
107 C_LOGE("RDB: Error during finalizing statement: %s",
108 sqlite3_errmsg(p_db));
114 * Function called when the target database is busy.
115 * We attempt to access the database every
116 * RDB_TIME_BETWEEN_ATTEMPTS seconds
118 * @param not_used not used
119 * @param i_attempt number of the attempt
120 * @return 0 when stops waiting
123 static int database_busy_handler(void *not_used UNUSED,
126 if(i_attempt > RDB_MAX_QUERY_ATTEMPTS) {
127 // I ain't gonna wait for you forever!
128 C_LOGE("RDB: Database busy for too long.");
131 C_LOGW("RDB: Database busy, waiting");
132 sleep(RDB_TIME_BETWEEN_ATTEMPTS);
137 int open_rdb_connection(sqlite3 **p_db)
144 int ret = sqlite3_open_v2(RDB_PATH,
149 C_LOGE("RDB: Error opening the database: Unable to allocate memory.");
150 return PC_ERR_DB_CONNECTION;
152 if(ret != SQLITE_OK) {
153 C_LOGE("RDB: Error opening the database: %s", sqlite3_errmsg(*p_db));
154 return PC_ERR_DB_CONNECTION;
157 //Register busy handler:
158 if(sqlite3_busy_handler(*p_db, database_busy_handler, NULL) != SQLITE_OK) {
159 C_LOGE("RDB: Error opening the database: %s", sqlite3_errmsg(*p_db));
160 return PC_ERR_DB_CONNECTION;
164 if(sqlite3_enable_load_extension(*p_db, 1)) {
165 C_LOGE("RDB: Error enabling extensions: %s", sqlite3_errmsg(*p_db));
166 return PC_ERR_DB_CONNECTION;
169 if(sqlite3_load_extension(*p_db,
170 "/usr/lib/librules-db-sql-udf.so", 0,
171 &p_err_msg) != SQLITE_OK) {
173 C_LOGE("RDB: Error during loading librules-db-sql-udf.so: %s",
175 sqlite3_free(p_err_msg);
176 return PC_ERR_DB_CONNECTION;
178 sqlite3_free(p_err_msg);
181 // Create the temporary tables:
182 if(sqlite3_exec(*p_db,
183 "CREATE TEMPORARY TABLE history_smack_rule( \
184 subject VARCHAR NOT NULL, \
185 object VARCHAR NOT NULL, \
186 access INTEGER NOT NULL); \
188 CREATE TEMPORARY TABLE modified_label( \
189 name VARCHAR NOT NULL, \
192 CREATE TEMPORARY TABLE all_smack_binary_rule_modified( \
193 subject VARCHAR NOT NULL, \
194 object VARCHAR NOT NULL, \
195 access INTEGER NOT NULL); \
197 CREATE TEMPORARY TABLE history_smack_rule_modified( \
198 subject VARCHAR NOT NULL, \
199 object VARCHAR NOT NULL, \
200 access INTEGER NOT NULL); \
202 CREATE TEMPORARY VIEW modified_smack_rules AS \
203 SELECT subject, object, \
204 access_to_str(access_add) AS access_add, \
205 access_to_str(access_del) AS access_del \
207 SELECT subject, object, \
208 s1.access & ~s2.access AS access_add, \
209 s2.access & ~s1.access AS access_del \
210 FROM all_smack_binary_rule_modified AS s1 \
211 INNER JOIN history_smack_rule_modified AS s2 \
212 USING (subject, object) \
213 WHERE s1.access != s2.access \
215 SELECT subject, object, \
216 s1.access AS access_add, \
218 FROM all_smack_binary_rule_modified s1 \
219 LEFT JOIN history_smack_rule_modified s2 \
220 USING (subject, object) \
221 WHERE s2.subject IS NULL AND \
224 SELECT subject, object, \
226 s1.access AS access_del \
227 FROM history_smack_rule_modified s1 \
228 LEFT JOIN all_smack_binary_rule_modified s2 \
229 USING (subject, object) \
230 WHERE s2.subject IS NULL AND \
233 ORDER BY subject, object ASC; \
234 PRAGMA foreign_keys = ON; \
236 0, 0, 0) != SQLITE_OK) {
237 C_LOGE("RDB: Error during preparing script: %s", sqlite3_errmsg(*p_db));
238 return PC_ERR_DB_OPERATION;
241 return PC_OPERATION_SUCCESS;
245 int prepare_stmt(sqlite3 *p_db,
246 sqlite3_stmt **pp_stmt,
247 const char *const s_sql,
250 int ret = PC_ERR_DB_QUERY_PREP;
251 char *s_query = NULL;
253 va_start(args, s_sql);
255 s_query = sqlite3_vmprintf(s_sql, args);
257 if(s_query == NULL) {
258 C_LOGE("RDB: Error during preparing statement: Unable to allocate enough memory.");
259 ret = PC_ERR_DB_QUERY_PREP;
263 if(sqlite3_prepare_v2(p_db,
268 C_LOGE("RDB: Error during preparing statement: %s", sqlite3_errmsg(p_db));
269 ret = PC_ERR_DB_QUERY_PREP;
273 if(*pp_stmt == NULL) {
274 C_LOGE("RDB: Error during preparing statement: SQL statement is probably empty.");
275 ret = PC_ERR_DB_QUERY_PREP;
279 ret = PC_OPERATION_SUCCESS;
283 sqlite3_free(s_query);
288 int check_app_label_internal(sqlite3 *p_db,
289 const char *const s_label_name)
291 RDB_LOG_ENTRY_PARAM("%s", s_label_name);
293 int ret = PC_ERR_DB_OPERATION;
294 sqlite3_stmt *p_stmt = NULL;
296 ret = prepare_stmt(p_db, &p_stmt,
297 "SELECT COUNT(application_view.name) \
298 FROM application_view \
299 WHERE application_view.name=%Q \
302 if(ret != PC_OPERATION_SUCCESS) goto finish;
304 ret = sqlite3_step(p_stmt);
305 if(ret == SQLITE_ROW) {
306 switch(sqlite3_column_int(p_stmt, RDB_FIRST_COLUMN)) {
307 case 0: ret = PC_OPERATION_SUCCESS; break;
308 case 1: ret = PC_ERR_DB_LABEL_TAKEN; break;
312 C_LOGE("RDB: Error during stepping: %s", sqlite3_errmsg(p_db));
313 ret = PC_ERR_DB_QUERY_STEP;
316 if(sqlite3_finalize(p_stmt) < 0)
317 C_LOGE("RDB: Error during finalizing statement: %s",
318 sqlite3_errmsg(p_db));
323 int check_label_internal(sqlite3 *p_db,
324 const char *const s_label_name)
326 RDB_LOG_ENTRY_PARAM("%s", s_label_name);
328 int ret = PC_ERR_DB_OPERATION;
329 sqlite3_stmt *p_stmt = NULL;
331 ret = prepare_stmt(p_db, &p_stmt,
332 "SELECT COUNT(label.name) \
333 FROM label WHERE name=%Q LIMIT 1",
336 if(ret != PC_OPERATION_SUCCESS) goto finish;
338 ret = sqlite3_step(p_stmt);
339 if(ret == SQLITE_ROW) {
340 switch(sqlite3_column_int(p_stmt, RDB_FIRST_COLUMN)) {
341 case 0: ret = PC_OPERATION_SUCCESS; break;
342 case 1: ret = PC_ERR_DB_LABEL_TAKEN; break;
346 C_LOGE("RDB: Error during stepping: %s", sqlite3_errmsg(p_db));
347 ret = PC_ERR_DB_QUERY_STEP;
351 if(sqlite3_finalize(p_stmt) < 0)
352 C_LOGE("RDB: Error during finalizing statement: %s",
353 sqlite3_errmsg(p_db));
358 int add_app_internal(sqlite3 *p_db,
359 const char *const s_label_name)
361 RDB_LOG_ENTRY_PARAM("%s", s_label_name);
363 int ret = PC_ERR_DB_OPERATION;
364 sqlite3_stmt *p_stmt = NULL;
366 ret = prepare_stmt(p_db, &p_stmt,
367 "INSERT into application_view(name) VALUES(%Q)",
369 if(ret != PC_OPERATION_SUCCESS) goto finish;
371 ret = step_and_convert_returned_value(p_stmt);
373 if(sqlite3_finalize(p_stmt) < 0)
374 C_LOGE("RDB: Error during finalizing statement: %s",
375 sqlite3_errmsg(p_db));
380 int remove_app_internal(sqlite3 *p_db,
381 const char *const s_label_name)
383 RDB_LOG_ENTRY_PARAM("%s", s_label_name);
385 int ret = PC_ERR_DB_OPERATION;
386 sqlite3_stmt *p_stmt = NULL;
388 ret = prepare_stmt(p_db, &p_stmt,
389 "DELETE FROM application_view \
390 WHERE application_view.name=%Q",
393 if(ret != PC_OPERATION_SUCCESS) goto finish;
395 ret = step_and_convert_returned_value(p_stmt);
397 if(sqlite3_finalize(p_stmt) < 0)
398 C_LOGE("RDB: Error during finalizing statement: %s",
399 sqlite3_errmsg(p_db));
404 int add_path_internal(sqlite3 *p_db,
405 const char *const s_owner_label_name,
406 const char *const s_path_label_name,
407 const char *const s_path,
408 const char *const s_access,
409 const char *const s_type)
411 RDB_LOG_ENTRY_PARAM("%s %s %s %s %s",
412 s_owner_label_name, s_path_label_name,
413 s_path, s_access, s_type);
415 int ret = PC_ERR_DB_OPERATION;
416 sqlite3_stmt *p_stmt = NULL;
418 ret = prepare_stmt(p_db, &p_stmt,
419 "INSERT INTO path_view(owner_app_label_name, \
424 VALUES(%Q, %Q, %Q, %Q, %Q);",
425 s_owner_label_name, s_path,
426 s_path_label_name, s_access, s_type);
427 if(ret != PC_OPERATION_SUCCESS) goto finish;
429 ret = step_and_convert_returned_value(p_stmt);
431 if(sqlite3_finalize(p_stmt) < 0)
432 C_LOGE("RDB: Error during finalizing statement: %s",
433 sqlite3_errmsg(p_db));
438 int check_permission_internal(sqlite3 *p_db,
439 const char *const s_permission_name,
440 const char *const s_permission_type_name)
442 RDB_LOG_ENTRY_PARAM("%s %s", s_permission_name, s_permission_type_name);
444 int ret = PC_ERR_DB_OPERATION;
445 sqlite3_stmt *p_stmt = NULL;
447 ret = prepare_stmt(p_db, &p_stmt,
448 "SELECT COUNT(SELECT permission_view.permission_id \
449 FROM permission_view \
453 s_permission_name, s_permission_type_name);
455 if(ret != PC_OPERATION_SUCCESS) goto finish;
457 ret = sqlite3_step(p_stmt);
458 if(ret == SQLITE_ROW) {
459 switch(sqlite3_column_int(p_stmt, RDB_FIRST_COLUMN)) {
460 case 0: ret = PC_OPERATION_SUCCESS; break; // No such permission
461 case 1: ret = PC_PERMISSION_EXISTS; break; // Permission exists
465 C_LOGE("RDB: Error during stepping: %s", sqlite3_errmsg(p_db));
466 ret = PC_ERR_DB_QUERY_STEP;
470 if(sqlite3_finalize(p_stmt) < 0)
471 C_LOGE("RDB: Error during finalizing statement: %s",
472 sqlite3_errmsg(p_db));
477 int add_permission_internal(sqlite3 *p_db,
478 const char *const s_permission_name,
479 const char *const s_permission_type_name)
481 RDB_LOG_ENTRY_PARAM("%s %s", s_permission_name, s_permission_type_name);
483 int ret = PC_ERR_DB_OPERATION;
484 sqlite3_stmt *p_stmt = NULL;
486 ret = prepare_stmt(p_db, &p_stmt,
487 "INSERT INTO permission_view(name, type_name) \
489 s_permission_name, s_permission_type_name);
491 if(ret != PC_OPERATION_SUCCESS) goto finish;
493 ret = step_and_convert_returned_value(p_stmt);
495 if(sqlite3_finalize(p_stmt) < 0)
496 C_LOGE("RDB: Error during finalizing statement: %s",
497 sqlite3_errmsg(p_db));
502 int get_permission_id_internal(sqlite3 *p_db,
503 const char *const s_permission_name,
504 const char *const s_permission_type_name,
505 sqlite3_int64 *p_permission_id)
507 RDB_LOG_ENTRY_PARAM("%s %s", s_permission_name, s_permission_type_name);
509 int ret = PC_ERR_DB_OPERATION;
510 sqlite3_stmt *p_stmt = NULL;
512 ret = prepare_stmt(p_db, &p_stmt,
513 "SELECT permission_view.permission_id \
514 FROM permission_view \
515 WHERE permission_view.name = %Q AND \
516 permission_view.type_name = %Q \
518 s_permission_name, s_permission_type_name);
519 if(ret != PC_OPERATION_SUCCESS) goto finish;
521 ret = sqlite3_step(p_stmt);
522 if(ret == SQLITE_ROW) {
523 ret = PC_OPERATION_SUCCESS;
524 *p_permission_id = sqlite3_column_int(p_stmt, RDB_FIRST_COLUMN);
525 } else if(ret == SQLITE_DONE) {
526 C_LOGW("RDB: There is no permission_id for %s %s", s_permission_name, s_permission_type_name);
527 ret = PC_ERR_DB_OPERATION;
530 C_LOGE("RDB: Error during stepping: %s", sqlite3_errmsg(p_db));
531 ret = PC_ERR_DB_QUERY_STEP;
535 if(sqlite3_finalize(p_stmt) < 0)
536 C_LOGE("RDB: Error during finalizing statement: %s",
537 sqlite3_errmsg(p_db));
543 int parse_rule(const char *const s_rule,
548 int ret = PC_OPERATION_SUCCESS;
549 char *tmp_s_rule = NULL;
550 const char *tmp_s_subject = NULL;
551 const char *tmp_s_object = NULL;
552 const char *tmp_s_access = NULL;
553 char *saveptr = NULL;
555 // Parse subject, object and access:
556 tmp_s_rule = strdup(s_rule);
557 tmp_s_subject = strtok_r(tmp_s_rule, " \t\n", &saveptr);
558 tmp_s_object = strtok_r(NULL, " \t\n", &saveptr);
559 tmp_s_access = strtok_r(NULL, " \t\n", &saveptr);
561 // Check rule validity:
562 if(tmp_s_subject == NULL ||
563 tmp_s_object == NULL ||
564 tmp_s_access == NULL ||
565 strtok_r(NULL, " \t\n", &saveptr) != NULL) {
566 C_LOGE("RDB: Incorrect rule format: %s", s_rule);
567 ret = PC_ERR_INVALID_PARAM;
572 strcpy(s_subject, tmp_s_subject);
573 strcpy(s_object, tmp_s_object);
574 strcpy(s_access, tmp_s_access);
576 if(tmp_s_rule) free(tmp_s_rule);
581 int add_permission_rules_internal(sqlite3 *p_db,
582 sqlite3_int64 permission_id,
583 const char *const *const pp_smack_rules)
588 int ret = PC_OPERATION_SUCCESS;
589 sqlite3_stmt *p_stmt = NULL;
590 char s_subject[SMACK_LABEL_LEN + 1];
591 char s_object[SMACK_LABEL_LEN + 1];
592 char s_access[ACC_LEN + 1];
594 // Prepare statement.
595 const char *s_query = "INSERT INTO \
596 permission_label_rule_view(permission_id,access,label_name,is_reverse) \
598 if(sqlite3_prepare_v2(p_db,
603 C_LOGE("RDB: Error during preparing statement: %s",
604 sqlite3_errmsg(p_db));
605 ret = PC_ERR_DB_QUERY_PREP;
609 for(i = 0; pp_smack_rules[i] != NULL ; ++i) {
610 C_LOGD("RDB: Granting permission: %s", pp_smack_rules[i]);
612 // Ignore empty lines
613 if(strspn(pp_smack_rules[i], " \t\n") == strlen(pp_smack_rules[i]))
616 ret = parse_rule(pp_smack_rules[i], s_subject, s_object, s_access);
617 if(ret != PC_OPERATION_SUCCESS) goto finish;
619 // Bind values to the statement and run it:
620 sqlite3_bind_int(p_stmt, 1, permission_id);
621 sqlite3_bind_text(p_stmt, 2, s_access, RDB_AUTO_DETERM_SIZE, 0);
622 if(!strcmp(s_subject, SMACK_APP_LABEL_TEMPLATE)) {
624 sqlite3_bind_text(p_stmt, 3, s_object, RDB_AUTO_DETERM_SIZE, 0);
625 sqlite3_bind_int(p_stmt, 4, 0);
627 } else if(!strcmp(s_object, SMACK_APP_LABEL_TEMPLATE)) {
628 sqlite3_bind_text(p_stmt, 3, s_subject, RDB_AUTO_DETERM_SIZE, 0);
629 sqlite3_bind_int(p_stmt, 4, 1);
632 C_LOGE("RDB: Incorrect rule format: %s", pp_smack_rules[i]);
633 ret = PC_ERR_INVALID_PARAM;
637 // Perform the insert
638 ret = step_and_convert_returned_value(p_stmt);
639 if(ret != PC_OPERATION_SUCCESS) goto finish;
641 // Reset and unbind statement:
642 if(sqlite3_reset(p_stmt) != SQLITE_OK) {
643 C_LOGE("RDB: Error reseting statement: %s",
644 sqlite3_errmsg(p_db));
645 ret = PC_ERR_DB_QUERY_STEP;
648 if(sqlite3_clear_bindings(p_stmt) != SQLITE_OK) {
649 C_LOGE("RDB: Error reseting statement: %s",
650 sqlite3_errmsg(p_db));
651 ret = PC_ERR_DB_QUERY_STEP;
657 if(sqlite3_finalize(p_stmt) < 0)
658 C_LOGE("RDB: Error during finalizing statement: %s",
659 sqlite3_errmsg(p_db));
664 int get_app_id_internal(sqlite3 *p_db,
666 const char *const s_app_label_name)
668 RDB_LOG_ENTRY_PARAM("%s", s_app_label_name);
670 int ret = PC_ERR_DB_OPERATION;
671 sqlite3_stmt *p_stmt = NULL;
673 ret = prepare_stmt(p_db, &p_stmt,
674 "SELECT application_view.app_id \
675 FROM application_view \
676 WHERE application_view.name = %Q",
679 if(ret != PC_OPERATION_SUCCESS) goto finish;
681 ret = sqlite3_step(p_stmt);
682 if(ret == SQLITE_ROW) {
683 ret = PC_OPERATION_SUCCESS;
684 *pi_app_id = sqlite3_column_int(p_stmt, RDB_FIRST_COLUMN);
686 } else if(ret == SQLITE_DONE) {
687 C_LOGW("RDB: There is no app_id for %s", s_app_label_name);
688 ret = PC_ERR_DB_OPERATION;
691 C_LOGE("RDB: Error during stepping: %s", sqlite3_errmsg(p_db));
692 ret = PC_ERR_DB_QUERY_STEP;
696 if(sqlite3_finalize(p_stmt) < 0)
697 C_LOGE("RDB: Error during finalizing statement: %s",
698 sqlite3_errmsg(p_db));
703 int add_app_permission_internal(sqlite3 *p_db,
705 const char *const s_permission_name,
706 const char *const s_permission_type_name,
707 const bool b_is_volatile_new,
708 const bool b_is_enabled_new)
710 RDB_LOG_ENTRY_PARAM("%d %s %s %d %d", i_app_id,
711 s_permission_name, s_permission_type_name,
712 b_is_volatile_new, b_is_enabled_new);
715 int ret = PC_ERR_DB_OPERATION;
716 sqlite3_stmt *p_stmt = NULL;
718 ret = prepare_stmt(p_db, &p_stmt,
720 app_permission_view(app_id, name, type_name, \
721 is_volatile, is_enabled) \
722 VALUES(%d,%Q,%Q,%d,%d)",
723 i_app_id, s_permission_name, s_permission_type_name,
724 (int)b_is_volatile_new, (int)b_is_enabled_new);
726 if(ret != PC_OPERATION_SUCCESS) goto finish;
728 ret = step_and_convert_returned_value(p_stmt);
730 if(sqlite3_finalize(p_stmt) < 0)
731 C_LOGE("RDB: Error during finalizing statement: %s",
732 sqlite3_errmsg(p_db));
737 int switch_app_permission_internal(sqlite3 *p_db,
739 const char *const s_permission_name,
740 const char *const s_permission_type_name,
741 const bool b_is_enabled_new)
743 RDB_LOG_ENTRY_PARAM("%d %s %s %d", i_app_id,
744 s_permission_name, s_permission_type_name,
747 int ret = PC_ERR_DB_OPERATION;
748 sqlite3_stmt *p_stmt = NULL;
750 ret = prepare_stmt(p_db, &p_stmt,
751 "UPDATE app_permission_view \
753 WHERE app_id = %d AND \
756 b_is_enabled_new, i_app_id,
757 s_permission_name, s_permission_type_name);
759 if(ret != PC_OPERATION_SUCCESS) goto finish;
760 ret = step_and_convert_returned_value(p_stmt);
762 if(sqlite3_finalize(p_stmt) < 0)
763 C_LOGE("RDB: Error during finalizing statement: %s",
764 sqlite3_errmsg(p_db));
769 int update_app_permission_internal(sqlite3 *p_db,
771 const int i_permission_id,
772 const bool b_is_volatile_new,
773 const bool b_is_enabled_new)
775 RDB_LOG_ENTRY_PARAM("%d %d %d %d",
776 i_app_id, i_permission_id,
777 b_is_volatile_new, b_is_enabled_new);
779 int ret = PC_ERR_DB_OPERATION;
780 sqlite3_stmt *p_stmt = NULL;
782 ret = prepare_stmt(p_db, &p_stmt,
783 "UPDATE app_permission \
784 SET is_volatile = %d, is_enabled=%d \
785 WHERE app_id = %d AND permission_id = %d",
786 b_is_volatile_new, b_is_enabled_new,
787 i_app_id, i_permission_id);
789 if(ret != PC_OPERATION_SUCCESS) goto finish;
790 ret = step_and_convert_returned_value(p_stmt);
792 if(sqlite3_finalize(p_stmt) < 0)
793 C_LOGE("RDB: Error during finalizing statement: %s",
794 sqlite3_errmsg(p_db));
799 int change_app_permission_internal(sqlite3 *p_db,
801 const char *const s_permission_name,
802 const char *const s_permission_type_name,
803 int i_is_volatile_new,
804 int i_is_enabled_new)
806 RDB_LOG_ENTRY_PARAM("%d %d %d %d %d", i_app_id,
807 s_permission_name, s_permission_type_name,
808 i_is_volatile_new, i_is_enabled_new);
810 int ret = PC_ERR_DB_OPERATION;
811 sqlite3_stmt *p_stmt = NULL;
812 int i_is_volatile_old, i_is_enabled_old, i_permission_id;
814 ret = prepare_stmt(p_db, &p_stmt,
815 "SELECT is_volatile, is_enabled, permission_id \
816 FROM app_permission_list_view \
817 WHERE app_id = %d AND \
818 permission_name=%Q AND \
819 permission_type_name=%Q LIMIT 1",
820 i_app_id, s_permission_name, s_permission_type_name);
821 if(ret != PC_OPERATION_SUCCESS) goto finish;
823 ret = sqlite3_step(p_stmt);
824 if(ret == SQLITE_ROW) {
825 // Phi, I already have this permission...
826 i_is_volatile_old = sqlite3_column_int(p_stmt, RDB_FIRST_COLUMN);
827 i_is_enabled_old = sqlite3_column_int(p_stmt, RDB_SECOND_COLUMN);
829 if(i_is_volatile_old == 1 && i_is_volatile_new == 0) {
830 // Confucius say, No man can down-cast volatility.
831 C_LOGE("RDB: Down-casting volatility is forbidden.");
832 ret = PC_ERR_DB_PERM_FORBIDDEN;
836 if(i_is_volatile_old == i_is_volatile_new &&
837 i_is_enabled_old == i_is_enabled_new) {
838 // There is no change. Nice.
839 C_LOGD("RDB: Permission %s %s already exists.", s_permission_name, s_permission_type_name);
840 ret = PC_OPERATION_SUCCESS;
844 i_permission_id = sqlite3_column_int(p_stmt, RDB_THIRD_COLUMN);
846 // Finalize statement
847 if(sqlite3_finalize(p_stmt) < 0)
848 C_LOGE("RDB: Error during finalizing statement: %s",
849 sqlite3_errmsg(p_db));
852 C_LOGD("RDB: Updating permission %s %s to application.", s_permission_name, s_permission_type_name);
853 ret = update_app_permission_internal(p_db,
859 } else if(ret == SQLITE_DONE) {
860 // Wow! A brand new permission! Omnomnom...
862 if(sqlite3_finalize(p_stmt) < 0)
863 C_LOGE("RDB: Error during finalizing statement: %s",
864 sqlite3_errmsg(p_db));
867 C_LOGD("RDB: Adding permission %s %s to application.", s_permission_name, s_permission_type_name);
868 ret = add_app_permission_internal(p_db,
871 s_permission_type_name,
875 C_LOGE("RDB: Error during stepping: %s", sqlite3_errmsg(p_db));
876 ret = PC_ERR_DB_QUERY_STEP;
880 if(p_stmt && sqlite3_finalize(p_stmt) < 0)
881 C_LOGE("RDB: Error during finalizing statement: %s",
882 sqlite3_errmsg(p_db));
887 int revoke_app_permissions_internal(sqlite3 *p_db,
888 const char *const s_app_label_name)
890 RDB_LOG_ENTRY_PARAM("%s", s_app_label_name);
892 int ret = PC_ERR_DB_OPERATION;
893 sqlite3_stmt *p_stmt = NULL;
895 ret = prepare_stmt(p_db, &p_stmt,
896 "DELETE FROM app_permission_view \
897 WHERE app_permission_view.app_name=%Q;",
900 if(ret != PC_OPERATION_SUCCESS) goto finish;
902 ret = step_and_convert_returned_value(p_stmt);
904 if(sqlite3_finalize(p_stmt) < 0)
905 C_LOGE("RDB: Error during finalizing statement: %s",
906 sqlite3_errmsg(p_db));
911 int reset_app_permissions_internal(sqlite3 *p_db,
912 const char *const s_app_label_name)
914 RDB_LOG_ENTRY_PARAM("%s", s_app_label_name);
916 int ret = PC_ERR_DB_OPERATION;
917 sqlite3_stmt *p_stmt = NULL;
919 ret = prepare_stmt(p_db, &p_stmt,
920 "DELETE FROM app_permission_volatile_view \
921 WHERE app_permission_volatile_view.app_name=%Q;",
924 if(ret != PC_OPERATION_SUCCESS) goto finish;
926 ret = step_and_convert_returned_value(p_stmt);
928 if(sqlite3_finalize(p_stmt) < 0)
929 C_LOGE("RDB: Error during finalizing statement: %s",
930 sqlite3_errmsg(p_db));
935 int save_smack_rules(sqlite3 *p_db)
939 if(sqlite3_exec(p_db,
940 "DELETE FROM history_smack_rule",
941 0, 0, 0) != SQLITE_OK) {
942 C_LOGE("RDB: Error during clearing history table: %s",
943 sqlite3_errmsg(p_db));
944 return PC_ERR_DB_OPERATION;
946 if(sqlite3_exec(p_db,
947 "INSERT INTO history_smack_rule \
948 SELECT subject, object, access \
949 FROM all_smack_binary_rules",
950 0, 0, 0) != SQLITE_OK) {
951 C_LOGE("RDB: Error during inserting into history_smack_rule table: %s",
952 sqlite3_errmsg(p_db));
953 return PC_ERR_DB_OPERATION;
956 // TODO: Maybe don't use index?
957 if(sqlite3_exec(p_db,
958 "CREATE INDEX history_smack_rule_subject_object_index \
959 ON history_smack_rule(subject, object)",
960 0, 0, 0) != SQLITE_OK) {
961 C_LOGE("RDB: Error during indexing history_smack_rule table: %s",
962 sqlite3_errmsg(p_db));
963 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);