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
43 * Reset and unbind statement. Used in functions that use bindings.
44 * @param p_stmt SQLite3 statement
45 * @return PC_OPERATION_SUCCESS on success, error code otherwise
47 static int reset_and_unbind_stmt(sqlite3_stmt *p_stmt)
49 if(sqlite3_clear_bindings(p_stmt) != SQLITE_OK) {
50 C_LOGE("RDB: Error unbinding statement: %s",
51 sqlite3_errmsg(sqlite3_db_handle(p_stmt)));
52 return PC_ERR_DB_QUERY_STEP;
55 if(sqlite3_reset(p_stmt) != SQLITE_OK) {
56 C_LOGE("RDB: Error reseting statement: %s",
57 sqlite3_errmsg(sqlite3_db_handle(p_stmt)));
58 return PC_ERR_DB_QUERY_STEP;
60 return PC_OPERATION_SUCCESS;
66 * Helper function. Use on INSERT or DELETE or UPDATE, when not interested in returned value
68 * @ingroup RDB: internal functions
70 * @param p_stmt SQLite3 statement
71 * @return PC_OPERATION_SUCCESS on success, error code otherwise
73 static int step_and_convert_returned_value(sqlite3_stmt *p_stmt)
75 if(sqlite3_step(p_stmt) == SQLITE_DONE) {
76 return PC_OPERATION_SUCCESS;
78 C_LOGE("RDB: Error during stepping: %s",
79 sqlite3_errmsg(sqlite3_db_handle(p_stmt)));
80 return PC_ERR_DB_QUERY_STEP;
84 int add_modified_label_internal(sqlite3 *p_db, const char *const s_label_name)
86 int ret = PC_OPERATION_SUCCESS;
87 sqlite3_stmt *p_stmt = NULL;
88 ret = prepare_stmt(p_db, &p_stmt,
89 "INSERT OR IGNORE INTO modified_label(name) VALUES(%Q)",
91 if(ret != PC_OPERATION_SUCCESS) goto finish;
93 ret = step_and_convert_returned_value(p_stmt);
95 if(sqlite3_finalize(p_stmt) < 0)
96 C_LOGE("RDB: Error during finalizing statement: %s",
97 sqlite3_errmsg(p_db));
102 int add_modified_permission_internal(sqlite3 *p_db, sqlite3_int64 i_permission_id)
104 int ret = PC_OPERATION_SUCCESS;
105 sqlite3_stmt *p_stmt = NULL;
106 ret = prepare_stmt(p_db, &p_stmt,
107 "INSERT OR IGNORE INTO modified_label(name) \
108 SELECT app_permission_view.app_name \
109 FROM app_permission_view \
110 WHERE app_permission_view.permission_id = %d",
112 if(ret != PC_OPERATION_SUCCESS) goto finish;
114 ret = step_and_convert_returned_value(p_stmt);
116 if(sqlite3_finalize(p_stmt) < 0)
117 C_LOGE("RDB: Error during finalizing statement: %s",
118 sqlite3_errmsg(p_db));
123 int add_modified_apps_path_internal(sqlite3 *p_db,
124 const char *const s_app_label_name)
126 int ret = PC_OPERATION_SUCCESS;
127 sqlite3_stmt *p_stmt = NULL;
128 ret = prepare_stmt(p_db, &p_stmt,
129 "INSERT OR IGNORE INTO modified_label(name) \
130 SELECT path_view.path_label_name \
132 WHERE path_view.owner_app_label_name = %Q",
134 if(ret != PC_OPERATION_SUCCESS) goto finish;
136 ret = step_and_convert_returned_value(p_stmt);
138 if(sqlite3_finalize(p_stmt) < 0)
139 C_LOGE("RDB: Error during finalizing statement: %s",
140 sqlite3_errmsg(p_db));
145 * Function called when the target database is busy.
146 * We attempt to access the database every
147 * RDB_TIME_BETWEEN_ATTEMPTS seconds
149 * @param not_used not used
150 * @param i_attempt number of the attempt
151 * @return 0 when stops waiting
154 static int database_busy_handler(void *not_used UNUSED,
157 if(i_attempt > RDB_MAX_QUERY_ATTEMPTS) {
158 // I ain't gonna wait for you forever!
159 C_LOGE("RDB: Database busy for too long.");
162 C_LOGW("RDB: Database busy, waiting");
163 sleep(RDB_TIME_BETWEEN_ATTEMPTS);
168 int open_rdb_connection(sqlite3 **p_db)
175 int ret = sqlite3_open_v2(RDB_PATH,
180 C_LOGE("RDB: Error opening the database: Unable to allocate memory.");
181 return PC_ERR_DB_CONNECTION;
183 if(ret != SQLITE_OK) {
184 C_LOGE("RDB: Error opening the database: %s", sqlite3_errmsg(*p_db));
185 return PC_ERR_DB_CONNECTION;
188 //Register busy handler:
189 if(sqlite3_busy_handler(*p_db, database_busy_handler, NULL) != SQLITE_OK) {
190 C_LOGE("RDB: Error opening the database: %s", sqlite3_errmsg(*p_db));
191 return PC_ERR_DB_CONNECTION;
195 if(sqlite3_enable_load_extension(*p_db, 1)) {
196 C_LOGE("RDB: Error enabling extensions: %s", sqlite3_errmsg(*p_db));
197 return PC_ERR_DB_CONNECTION;
200 if(sqlite3_load_extension(*p_db,
201 "/usr/lib/librules-db-sql-udf.so", 0,
202 &p_err_msg) != SQLITE_OK) {
204 C_LOGE("RDB: Error during loading librules-db-sql-udf.so: %s",
206 sqlite3_free(p_err_msg);
207 return PC_ERR_DB_CONNECTION;
209 sqlite3_free(p_err_msg);
212 // Create the temporary tables:
213 if(sqlite3_exec(*p_db,
214 "PRAGMA foreign_keys = ON; \
215 CREATE TEMPORARY TABLE history_smack_rule( \
216 subject VARCHAR NOT NULL, \
217 object VARCHAR NOT NULL, \
218 access INTEGER NOT NULL); \
220 CREATE TEMPORARY TABLE modified_label( \
221 name VARCHAR NOT NULL, \
224 CREATE TEMPORARY TABLE all_smack_binary_rule_modified( \
225 subject VARCHAR NOT NULL, \
226 object VARCHAR NOT NULL, \
227 access INTEGER NOT NULL); \
229 CREATE TEMPORARY TABLE history_smack_rule_modified( \
230 subject VARCHAR NOT NULL, \
231 object VARCHAR NOT NULL, \
232 access INTEGER NOT NULL); \
234 CREATE TEMPORARY VIEW modified_smack_rules AS \
235 SELECT subject, object, \
236 access_to_str(access_add) AS access_add, \
237 access_to_str(access_del) AS access_del \
239 SELECT subject, object, \
240 s1.access & ~s2.access AS access_add, \
241 s2.access & ~s1.access AS access_del \
242 FROM all_smack_binary_rule_modified AS s1 \
243 INNER JOIN history_smack_rule_modified AS s2 \
244 USING (subject, object) \
245 WHERE s1.access != s2.access \
247 SELECT subject, object, \
248 s1.access AS access_add, \
250 FROM all_smack_binary_rule_modified s1 \
251 LEFT JOIN history_smack_rule_modified s2 \
252 USING (subject, object) \
253 WHERE s2.subject IS NULL AND \
256 SELECT subject, object, \
258 s1.access AS access_del \
259 FROM history_smack_rule_modified s1 \
260 LEFT JOIN all_smack_binary_rule_modified s2 \
261 USING (subject, object) \
262 WHERE s2.subject IS NULL AND \
265 ORDER BY subject, object ASC;",
266 0, 0, 0) != SQLITE_OK) {
267 C_LOGE("RDB: Error during preparing script: %s", sqlite3_errmsg(*p_db));
268 return PC_ERR_DB_OPERATION;
271 return PC_OPERATION_SUCCESS;
275 int prepare_stmt(sqlite3 *p_db,
276 sqlite3_stmt **pp_stmt,
277 const char *const s_sql,
280 int ret = PC_ERR_DB_QUERY_PREP;
281 char *s_query = NULL;
283 va_start(args, s_sql);
285 s_query = sqlite3_vmprintf(s_sql, args);
287 if(s_query == NULL) {
288 C_LOGE("RDB: Error during preparing statement: Unable to allocate enough memory.");
289 ret = PC_ERR_DB_QUERY_PREP;
293 if(sqlite3_prepare_v2(p_db,
298 C_LOGE("RDB: Error during preparing statement: %s", sqlite3_errmsg(p_db));
299 ret = PC_ERR_DB_QUERY_PREP;
303 if(*pp_stmt == NULL) {
304 C_LOGE("RDB: Error during preparing statement: SQL statement is probably empty.");
305 ret = PC_ERR_DB_QUERY_PREP;
309 ret = PC_OPERATION_SUCCESS;
313 sqlite3_free(s_query);
318 int check_app_label_internal(sqlite3 *p_db,
319 const char *const s_label_name)
321 RDB_LOG_ENTRY_PARAM("%s", s_label_name);
323 int ret = PC_ERR_DB_OPERATION;
324 sqlite3_stmt *p_stmt = NULL;
326 ret = prepare_stmt(p_db, &p_stmt,
328 FROM application_view \
329 WHERE application_view.name=%Q \
332 if(ret != PC_OPERATION_SUCCESS) goto finish;
334 ret = sqlite3_step(p_stmt);
335 if(ret == SQLITE_ROW) {
336 // There is such application label
337 ret = PC_ERR_DB_LABEL_TAKEN;
338 } else if(ret == SQLITE_DONE) {
339 // No such application label
340 ret = PC_OPERATION_SUCCESS;
342 C_LOGE("RDB: Error during stepping: %s", sqlite3_errmsg(p_db));
343 ret = PC_ERR_DB_QUERY_STEP;
346 if(sqlite3_finalize(p_stmt) < 0)
347 C_LOGE("RDB: Error during finalizing statement: %s",
348 sqlite3_errmsg(p_db));
353 int add_app_internal(sqlite3 *p_db,
354 const char *const s_label_name)
356 RDB_LOG_ENTRY_PARAM("%s", s_label_name);
358 int ret = PC_ERR_DB_OPERATION;
359 sqlite3_stmt *p_stmt = NULL;
361 ret = prepare_stmt(p_db, &p_stmt,
362 "INSERT into application_view(name) VALUES(%Q)",
364 if(ret != PC_OPERATION_SUCCESS) goto finish;
366 ret = step_and_convert_returned_value(p_stmt);
368 if(sqlite3_finalize(p_stmt) < 0)
369 C_LOGE("RDB: Error during finalizing statement: %s",
370 sqlite3_errmsg(p_db));
375 int remove_app_internal(sqlite3 *p_db,
376 const char *const s_label_name)
378 RDB_LOG_ENTRY_PARAM("%s", s_label_name);
380 int ret = PC_ERR_DB_OPERATION;
381 sqlite3_stmt *p_stmt = NULL;
383 ret = prepare_stmt(p_db, &p_stmt,
384 "DELETE FROM application_view \
385 WHERE application_view.name=%Q",
388 if(ret != PC_OPERATION_SUCCESS) goto finish;
390 ret = step_and_convert_returned_value(p_stmt);
392 if(sqlite3_finalize(p_stmt) < 0)
393 C_LOGE("RDB: Error during finalizing statement: %s",
394 sqlite3_errmsg(p_db));
399 int add_path_internal(sqlite3 *p_db,
400 const char *const s_owner_label_name,
401 const char *const s_path_label_name,
402 const char *const s_path,
403 const char *const s_access,
404 const char *const s_access_reverse,
405 const char *const s_type)
407 RDB_LOG_ENTRY_PARAM("%s %s %s %s %s %s",
408 s_owner_label_name, s_path_label_name,
409 s_path, s_access, s_access_reverse, s_type);
411 int ret = PC_ERR_DB_OPERATION;
412 sqlite3_stmt *p_stmt = NULL;
414 ret = prepare_stmt(p_db, &p_stmt,
415 "INSERT INTO path_view(owner_app_label_name, \
421 VALUES(%Q, %Q, %Q, %Q, %Q, %Q);",
422 s_owner_label_name, s_path, s_path_label_name,
423 s_access, s_access_reverse, s_type);
424 if(ret != PC_OPERATION_SUCCESS) goto finish;
426 ret = step_and_convert_returned_value(p_stmt);
428 if(sqlite3_finalize(p_stmt) < 0)
429 C_LOGE("RDB: Error during finalizing statement: %s",
430 sqlite3_errmsg(p_db));
435 int add_permission_internal(sqlite3 *p_db,
436 const char *const s_permission_name,
437 const char *const s_permission_type_name)
439 RDB_LOG_ENTRY_PARAM("%s %s", s_permission_name, s_permission_type_name);
441 int ret = PC_ERR_DB_OPERATION;
442 sqlite3_stmt *p_stmt = NULL;
444 ret = prepare_stmt(p_db, &p_stmt,
445 "INSERT INTO permission_view(name, type_name) \
447 s_permission_name, s_permission_type_name);
449 if(ret != PC_OPERATION_SUCCESS) goto finish;
451 ret = step_and_convert_returned_value(p_stmt);
453 if(sqlite3_finalize(p_stmt) < 0)
454 C_LOGE("RDB: Error during finalizing statement: %s",
455 sqlite3_errmsg(p_db));
460 int get_permission_id_internal(sqlite3 *p_db,
461 const char *const s_permission_name,
462 const char *const s_permission_type_name,
463 sqlite3_int64 *p_permission_id)
465 RDB_LOG_ENTRY_PARAM("%s %s", s_permission_name, s_permission_type_name);
467 int ret = PC_ERR_DB_OPERATION;
468 sqlite3_stmt *p_stmt = NULL;
470 ret = prepare_stmt(p_db, &p_stmt,
471 "SELECT permission_view.permission_id \
472 FROM permission_view \
473 WHERE permission_view.name = %Q AND \
474 permission_view.type_name = %Q \
476 s_permission_name, s_permission_type_name);
477 if(ret != PC_OPERATION_SUCCESS) goto finish;
479 ret = sqlite3_step(p_stmt);
480 if(ret == SQLITE_ROW) {
481 ret = PC_OPERATION_SUCCESS;
482 *p_permission_id = sqlite3_column_int(p_stmt, RDB_FIRST_COLUMN);
483 } else if(ret == SQLITE_DONE) {
484 C_LOGW("RDB: There is no permission_id for %s %s", s_permission_name, s_permission_type_name);
485 ret = PC_ERR_DB_OPERATION;
488 C_LOGE("RDB: Error during stepping: %s", sqlite3_errmsg(p_db));
489 ret = PC_ERR_DB_QUERY_STEP;
493 if(sqlite3_finalize(p_stmt) < 0)
494 C_LOGE("RDB: Error during finalizing statement: %s",
495 sqlite3_errmsg(p_db));
501 int prepare_stmts_for_bind(sqlite3 *p_db,
502 sqlite3_stmt **pp_stmt,
503 const char *const s_query)
505 if(sqlite3_prepare_v2(p_db,
510 C_LOGE("RDB: Error during preparing statement: %s",
511 sqlite3_errmsg(p_db));
512 return PC_ERR_DB_QUERY_PREP;
514 return PC_OPERATION_SUCCESS;
518 static int add_permission_label_rule(sqlite3_stmt *p_stmt,
519 const sqlite3_int64 i_permission_id,
520 const char *const s_label_name,
521 const char *const s_access,
522 const int i_is_reverse)
524 int ret = PC_OPERATION_SUCCESS;
526 // Bind values to the statement and run it:
527 // Bind returns SQLITE_OK == 0 on success
528 if(sqlite3_bind_int(p_stmt, 1, i_permission_id) ||
529 sqlite3_bind_text(p_stmt, 2, s_access, RDB_AUTO_DETERM_SIZE, 0) ||
530 sqlite3_bind_text(p_stmt, 3, s_label_name, RDB_AUTO_DETERM_SIZE, 0) ||
531 sqlite3_bind_int(p_stmt, 4, i_is_reverse)) {
532 C_LOGE("RDB: Error during binding to statement: %s",
533 sqlite3_errmsg(sqlite3_db_handle(p_stmt)));
534 ret = PC_ERR_DB_QUERY_BIND;
538 // Perform the insert
539 ret = step_and_convert_returned_value(p_stmt);
542 reset_and_unbind_stmt(p_stmt);
547 static int add_permission_permission_rule(sqlite3_stmt *p_stmt,
548 const sqlite3_int64 i_permission_id,
549 const sqlite3_int64 i_target_permission_id,
550 const char *const s_access,
551 const int i_is_reverse)
553 int ret = PC_OPERATION_SUCCESS;
555 if(sqlite3_bind_int(p_stmt, 1, i_permission_id) ||
556 sqlite3_bind_int(p_stmt, 2, i_target_permission_id) ||
557 sqlite3_bind_text(p_stmt, 3, s_access, RDB_AUTO_DETERM_SIZE, 0) ||
558 sqlite3_bind_int(p_stmt, 4, i_is_reverse)) {
559 C_LOGE("RDB: Error during binding to statement: %s",
560 sqlite3_errmsg(sqlite3_db_handle(p_stmt)));
561 ret = PC_ERR_DB_QUERY_BIND;
565 ret = step_and_convert_returned_value(p_stmt);
568 reset_and_unbind_stmt(p_stmt);
573 static int add_permission_app_path_type_rule(sqlite3_stmt *p_stmt,
574 const sqlite3_int64 i_permission_id,
575 const char *const s_path_type_name,
576 const char *const s_access,
577 const int i_is_reverse)
579 int ret = PC_OPERATION_SUCCESS;
581 if(sqlite3_bind_int(p_stmt, 1, i_permission_id) ||
582 sqlite3_bind_text(p_stmt, 2, s_path_type_name, RDB_AUTO_DETERM_SIZE, 0) ||
583 sqlite3_bind_text(p_stmt, 3, s_access, RDB_AUTO_DETERM_SIZE, 0) ||
584 sqlite3_bind_int(p_stmt, 4, i_is_reverse)) {
585 C_LOGE("RDB: Error during binding to statement: %s",
586 sqlite3_errmsg(sqlite3_db_handle(p_stmt)));
587 ret = PC_ERR_DB_QUERY_BIND;
591 ret = step_and_convert_returned_value(p_stmt);
594 reset_and_unbind_stmt(p_stmt);
598 int add_permission_rules_internal(sqlite3 *p_db,
599 const sqlite3_int64 i_permission_id,
600 const char *const *const pp_smack_rules)
604 int ret = PC_OPERATION_SUCCESS;
605 char s_label[SMACK_LABEL_LEN + 1];
606 char s_access[ACC_LEN + 1];
607 sqlite3_int64 i_all_apps_permission_id = 1;
608 int i_is_reverse = 0;
610 sqlite3_stmt *p_perm_to_label_stmt = NULL;
611 sqlite3_stmt *p_perm_to_perm_stmt = NULL;
612 sqlite3_stmt *p_perm_to_app_path_type_stmt = NULL;
614 // Prepare stmts. They are static, so we parse SQL only once per process and reuse it.
615 ret = prepare_stmts_for_bind(p_db, &p_perm_to_label_stmt,
616 "INSERT INTO permission_label_rule_view( \
617 permission_id, access, label_name, is_reverse) \
619 if(ret != PC_OPERATION_SUCCESS) goto finish;
621 ret = prepare_stmts_for_bind(p_db, &p_perm_to_perm_stmt,
622 "INSERT OR REPLACE INTO permission_permission_rule( \
623 permission_id, target_permission_id, \
624 access, is_reverse) \
625 VALUES(?,?,str_to_access(?),?)");
626 if(ret != PC_OPERATION_SUCCESS) goto finish;
629 ret = prepare_stmts_for_bind(p_db, &p_perm_to_app_path_type_stmt,
630 "INSERT INTO permission_app_path_type_rule_view( \
631 permission_id, app_path_type_name, access, is_reverse) \
633 if(ret != PC_OPERATION_SUCCESS) goto finish;
636 for(i = 0; pp_smack_rules[i] != NULL ; ++i) {
637 C_LOGD("RDB: Granting permission: %s", pp_smack_rules[i]);
639 // Ignore empty lines
640 if(strspn(pp_smack_rules[i], " \t\n") == strlen(pp_smack_rules[i]))
643 ret = parse_rule(pp_smack_rules[i], s_label, s_access, &i_is_reverse);
644 if(ret != PC_OPERATION_SUCCESS) goto finish;
646 // Interpret wildcards
647 if(s_label[0] != '~' &&
648 s_label[strlen(s_label) - 1] != '~') {
649 // It's not a wildcard!
650 ret = add_permission_label_rule(p_perm_to_label_stmt,
655 if(ret != PC_OPERATION_SUCCESS) goto finish;
657 } else if(!strcmp(s_label, "~ALL_APPS~")) {
658 ret = get_permission_id_internal(p_db,
661 &i_all_apps_permission_id);
662 if(ret != PC_OPERATION_SUCCESS) goto finish;
664 ret = add_permission_permission_rule(p_perm_to_perm_stmt,
666 i_all_apps_permission_id,
669 if(ret != PC_OPERATION_SUCCESS) goto finish;
671 } else if(!strcmp(s_label, "~ALL_APPS_WITH_SAME_PERMISSION~")) {
672 ret = add_permission_permission_rule(p_perm_to_perm_stmt,
677 if(ret != PC_OPERATION_SUCCESS) goto finish;
679 } else if(!strcmp(s_label, "~PUBLIC_PATH~")) {
680 ret = add_permission_app_path_type_rule(p_perm_to_app_path_type_stmt,
685 if(ret != PC_OPERATION_SUCCESS) goto finish;
687 } else if(!strcmp(s_label, "~GROUP_PATH~")) {
688 ret = add_permission_app_path_type_rule(p_perm_to_app_path_type_stmt,
693 if(ret != PC_OPERATION_SUCCESS) goto finish;
695 } else if(!strcmp(s_label, "~SETTINGS_PATH~")) {
696 ret = add_permission_app_path_type_rule(p_perm_to_app_path_type_stmt,
701 if(ret != PC_OPERATION_SUCCESS) goto finish;
705 ret = PC_OPERATION_SUCCESS;
708 if(p_perm_to_label_stmt &&
709 sqlite3_finalize(p_perm_to_label_stmt) < 0) {
710 C_LOGE("RDB: Error during finalizing statement: %s",
711 sqlite3_errmsg(p_db));
714 if(p_perm_to_perm_stmt &&
715 sqlite3_finalize(p_perm_to_perm_stmt) < 0) {
716 C_LOGE("RDB: Error during finalizing statement: %s",
717 sqlite3_errmsg(p_db));
720 if(p_perm_to_app_path_type_stmt &&
721 sqlite3_finalize(p_perm_to_app_path_type_stmt) < 0) {
722 C_LOGE("RDB: Error during finalizing statement: %s",
723 sqlite3_errmsg(p_db));
728 static int add_label_app_path_type_rule(sqlite3_stmt *p_stmt,
729 const char *const s_label_name,
730 const char *const s_path_type_name,
731 const char *const s_access,
732 const int i_is_reverse)
734 int ret = PC_OPERATION_SUCCESS;
736 if(sqlite3_bind_text(p_stmt, 1, s_label_name, RDB_AUTO_DETERM_SIZE, 0) ||
737 sqlite3_bind_text(p_stmt, 2, s_path_type_name, RDB_AUTO_DETERM_SIZE, 0) ||
738 sqlite3_bind_text(p_stmt, 3, s_access, RDB_AUTO_DETERM_SIZE, 0) ||
739 sqlite3_bind_int(p_stmt, 4, i_is_reverse)) {
740 C_LOGE("RDB: Error during binding to statement: %s",
741 sqlite3_errmsg(sqlite3_db_handle(p_stmt)));
742 ret = PC_ERR_DB_QUERY_BIND;
746 ret = step_and_convert_returned_value(p_stmt);
749 reset_and_unbind_stmt(p_stmt);
754 int add_additional_rules_internal(sqlite3 *p_db, const char *const *const pp_smack_rules)
757 int ret = PC_OPERATION_SUCCESS;
759 char s_subject[SMACK_LABEL_LEN + 1];
760 char s_object[SMACK_LABEL_LEN + 1];
761 char s_access[ACC_LEN + 1];
762 sqlite3_stmt *p_label_to_app_path_type_stmt = NULL;
764 char *ps_subject, *ps_object;
766 // Clear the label_app_path_type_rule table
767 if(sqlite3_exec(p_db, "DELETE FROM label_app_path_type_rule_view;", 0, 0, 0) != SQLITE_OK) {
768 C_LOGE("RDB: Error during clearing additional rules: %s", sqlite3_errmsg(p_db));
769 ret = PC_ERR_DB_OPERATION;
773 ret = prepare_stmts_for_bind(p_db, &p_label_to_app_path_type_stmt,
774 "INSERT INTO label_app_path_type_rule_view( \
775 label_name, app_path_type_name, access, is_reverse) \
777 if(ret != PC_OPERATION_SUCCESS) goto finish;
779 // Add rules to the database
780 for(i = 0; pp_smack_rules[i] != NULL ; ++i) {
782 // Ignore empty lines
783 if(strspn(pp_smack_rules[i], " \t\n") == strlen(pp_smack_rules[i]))
787 ret = tokenize_rule(pp_smack_rules[i], s_subject , s_object, s_access);
788 if(ret != PC_OPERATION_SUCCESS) goto finish;
790 if(is_wildcard(s_subject)) {
791 ps_subject = s_object;
792 ps_object = s_subject;
795 ps_subject = s_subject;
796 ps_object = s_object;
801 if(!smack_label_is_valid(ps_subject)) {
802 C_LOGE("Subject is not a valid label");
803 ret = PC_ERR_INVALID_PARAM;
807 // Add access to paths
808 if(!strcmp(ps_object, "~PUBLIC_PATH~")) {
809 ret = add_label_app_path_type_rule(p_label_to_app_path_type_stmt,
814 if(ret != PC_OPERATION_SUCCESS) goto finish;
816 } else if(!strcmp(ps_object, "~GROUP_PATH~")) {
817 ret = add_label_app_path_type_rule(p_label_to_app_path_type_stmt,
822 if(ret != PC_OPERATION_SUCCESS) goto finish;
824 } else if(!strcmp(ps_object, "~SETTINGS_PATH~")) {
825 ret = add_label_app_path_type_rule(p_label_to_app_path_type_stmt,
830 if(ret != PC_OPERATION_SUCCESS) goto finish;
831 } else if(!strcmp(ps_object, "~NPRUNTIME_PATH~")) {
832 ret = add_label_app_path_type_rule(p_label_to_app_path_type_stmt,
837 if(ret != PC_OPERATION_SUCCESS) goto finish;
841 // Mark label as modified
842 ret = add_modified_label_internal(p_db, ps_subject);
843 if(ret != PC_OPERATION_SUCCESS) goto finish;
847 if(p_label_to_app_path_type_stmt &&
848 sqlite3_finalize(p_label_to_app_path_type_stmt) < 0)
849 C_LOGE("RDB: Error during finalizing statement: %s",
850 sqlite3_errmsg(p_db));
854 int check_app_has_permission_internal(sqlite3 *p_db,
855 const char *const s_app_label_name,
856 const char *const s_permission_name,
857 const char *const s_permission_type_name,
858 bool *const p_is_enabled)
860 RDB_LOG_ENTRY_PARAM("%s %s %s", s_app_label_name,
861 s_permission_name, s_permission_type_name);
863 int ret = PC_ERR_DB_OPERATION;
864 sqlite3_stmt *p_stmt = NULL;
866 ret = prepare_stmt(p_db, &p_stmt,
868 FROM app_permission_view \
869 WHERE app_name = %Q AND \
873 s_app_label_name, s_permission_name, s_permission_type_name);
874 if(ret != PC_OPERATION_SUCCESS) goto finish;
876 ret = sqlite3_step(p_stmt);
877 if(ret == SQLITE_ROW) {
878 ret = PC_OPERATION_SUCCESS;
880 *p_is_enabled = (bool)sqlite3_column_int(p_stmt, RDB_FIRST_COLUMN);
881 } else if(ret == SQLITE_DONE) {
882 //no entry == permission not assigned
883 C_LOGD("RDB: Permission: %s of type: %s is not assigned to app: %s",
884 s_permission_name, s_permission_type_name, s_app_label_name);
885 ret = PC_OPERATION_SUCCESS;
886 *p_is_enabled = false;
887 } else if(ret == SQLITE_BUSY) {
888 //base locked in exclusive mode for too long
889 C_LOGE("RDB: Database is busy. RDB Connection Error returned.");
890 ret = PC_ERR_DB_CONNECTION;
892 C_LOGE("RDB: Error during stepping: %s", sqlite3_errmsg(p_db));
893 ret = PC_ERR_DB_QUERY_STEP;
897 if(sqlite3_finalize(p_stmt) < 0)
898 C_LOGE("RDB: Error during finalizing statement: %s",
899 sqlite3_errmsg(p_db));
903 int get_app_id_internal(sqlite3 *p_db,
905 const char *const s_app_label_name)
907 RDB_LOG_ENTRY_PARAM("%s", s_app_label_name);
909 int ret = PC_ERR_DB_OPERATION;
910 sqlite3_stmt *p_stmt = NULL;
912 ret = prepare_stmt(p_db, &p_stmt,
913 "SELECT application_view.app_id \
914 FROM application_view \
915 WHERE application_view.name = %Q",
918 if(ret != PC_OPERATION_SUCCESS) goto finish;
920 ret = sqlite3_step(p_stmt);
921 if(ret == SQLITE_ROW) {
922 ret = PC_OPERATION_SUCCESS;
923 *pi_app_id = sqlite3_column_int(p_stmt, RDB_FIRST_COLUMN);
925 } else if(ret == SQLITE_DONE) {
926 C_LOGW("RDB: There is no app_id for %s", s_app_label_name);
927 ret = PC_ERR_DB_OPERATION;
930 C_LOGE("RDB: Error during stepping: %s", sqlite3_errmsg(p_db));
931 ret = PC_ERR_DB_QUERY_STEP;
935 if(sqlite3_finalize(p_stmt) < 0)
936 C_LOGE("RDB: Error during finalizing statement: %s",
937 sqlite3_errmsg(p_db));
942 int add_app_permission_internal(sqlite3 *p_db,
944 const char *const s_permission_name,
945 const char *const s_permission_type_name,
946 const bool b_is_volatile_new,
947 const bool b_is_enabled_new)
949 RDB_LOG_ENTRY_PARAM("%d %s %s %d %d", i_app_id,
950 s_permission_name, s_permission_type_name,
951 b_is_volatile_new, b_is_enabled_new);
954 int ret = PC_ERR_DB_OPERATION;
955 sqlite3_stmt *p_stmt = NULL;
957 ret = prepare_stmt(p_db, &p_stmt,
959 app_permission_view(app_id, name, type_name, \
960 is_volatile, is_enabled) \
961 VALUES(%d,%Q,%Q,%d,%d)",
962 i_app_id, s_permission_name, s_permission_type_name,
963 (int)b_is_volatile_new, (int)b_is_enabled_new);
965 if(ret != PC_OPERATION_SUCCESS) goto finish;
967 ret = step_and_convert_returned_value(p_stmt);
969 if(sqlite3_finalize(p_stmt) < 0)
970 C_LOGE("RDB: Error during finalizing statement: %s",
971 sqlite3_errmsg(p_db));
976 int switch_app_permission_internal(sqlite3 *p_db,
978 const char *const s_permission_name,
979 const char *const s_permission_type_name,
980 const bool b_is_enabled_new)
982 RDB_LOG_ENTRY_PARAM("%d %s %s %d", i_app_id,
983 s_permission_name, s_permission_type_name,
986 int ret = PC_ERR_DB_OPERATION;
987 sqlite3_stmt *p_stmt = NULL;
989 ret = prepare_stmt(p_db, &p_stmt,
990 "UPDATE app_permission_view \
992 WHERE app_id = %d AND \
995 b_is_enabled_new, i_app_id,
996 s_permission_name, s_permission_type_name);
998 if(ret != PC_OPERATION_SUCCESS) goto finish;
999 ret = step_and_convert_returned_value(p_stmt);
1001 if(sqlite3_finalize(p_stmt) < 0)
1002 C_LOGE("RDB: Error during finalizing statement: %s",
1003 sqlite3_errmsg(p_db));
1008 int update_app_permission_internal(sqlite3 *p_db,
1010 const int i_permission_id,
1011 const bool b_is_volatile_new,
1012 const bool b_is_enabled_new)
1014 RDB_LOG_ENTRY_PARAM("%d %d %d %d",
1015 i_app_id, i_permission_id,
1016 b_is_volatile_new, b_is_enabled_new);
1018 int ret = PC_ERR_DB_OPERATION;
1019 sqlite3_stmt *p_stmt = NULL;
1021 ret = prepare_stmt(p_db, &p_stmt,
1022 "UPDATE app_permission \
1023 SET is_volatile = %d, is_enabled=%d \
1024 WHERE app_id = %d AND permission_id = %d",
1025 b_is_volatile_new, b_is_enabled_new,
1026 i_app_id, i_permission_id);
1028 if(ret != PC_OPERATION_SUCCESS) goto finish;
1029 ret = step_and_convert_returned_value(p_stmt);
1031 if(sqlite3_finalize(p_stmt) < 0)
1032 C_LOGE("RDB: Error during finalizing statement: %s",
1033 sqlite3_errmsg(p_db));
1038 int change_app_permission_internal(sqlite3 *p_db,
1040 const char *const s_permission_name,
1041 const char *const s_permission_type_name,
1042 int i_is_volatile_new,
1043 int i_is_enabled_new)
1045 RDB_LOG_ENTRY_PARAM("%d %s %s %d %d", i_app_id,
1046 s_permission_name, s_permission_type_name,
1047 i_is_volatile_new, i_is_enabled_new);
1049 int ret = PC_ERR_DB_OPERATION;
1050 sqlite3_stmt *p_stmt = NULL;
1051 int i_is_volatile_old, i_is_enabled_old, i_permission_id;
1053 ret = prepare_stmt(p_db, &p_stmt,
1054 "SELECT is_volatile, is_enabled, permission_id \
1055 FROM app_permission_list_view \
1056 WHERE app_id = %d AND \
1057 permission_name=%Q AND \
1058 permission_type_name=%Q LIMIT 1",
1059 i_app_id, s_permission_name, s_permission_type_name);
1060 if(ret != PC_OPERATION_SUCCESS) goto finish;
1062 ret = sqlite3_step(p_stmt);
1063 if(ret == SQLITE_ROW) {
1064 // Phi, I already have this permission...
1065 i_is_volatile_old = sqlite3_column_int(p_stmt, RDB_FIRST_COLUMN);
1066 i_is_enabled_old = sqlite3_column_int(p_stmt, RDB_SECOND_COLUMN);
1068 if(i_is_volatile_old == 1 && i_is_volatile_new == 0) {
1069 // Confucius say, No man can down-cast volatility.
1070 C_LOGE("RDB: Down-casting volatility is forbidden.");
1071 ret = PC_ERR_DB_PERM_FORBIDDEN;
1075 if(i_is_volatile_old == i_is_volatile_new &&
1076 i_is_enabled_old == i_is_enabled_new) {
1077 // There is no change. Nice.
1078 C_LOGD("RDB: Permission %s %s already exists.", s_permission_name, s_permission_type_name);
1079 ret = PC_OPERATION_SUCCESS;
1083 i_permission_id = sqlite3_column_int(p_stmt, RDB_THIRD_COLUMN);
1085 // Finalize statement
1086 if(sqlite3_finalize(p_stmt) < 0)
1087 C_LOGE("RDB: Error during finalizing statement: %s",
1088 sqlite3_errmsg(p_db));
1091 C_LOGD("RDB: Updating permission %s %s to application.", s_permission_name, s_permission_type_name);
1092 ret = update_app_permission_internal(p_db,
1098 } else if(ret == SQLITE_DONE) {
1099 // Wow! A brand new permission! Omnomnom...
1101 if(sqlite3_finalize(p_stmt) < 0)
1102 C_LOGE("RDB: Error during finalizing statement: %s",
1103 sqlite3_errmsg(p_db));
1106 C_LOGD("RDB: Adding permission %s %s to application.", s_permission_name, s_permission_type_name);
1107 ret = add_app_permission_internal(p_db,
1110 s_permission_type_name,
1114 C_LOGE("RDB: Error during stepping: %s", sqlite3_errmsg(p_db));
1115 ret = PC_ERR_DB_QUERY_STEP;
1119 if(p_stmt && sqlite3_finalize(p_stmt) < 0)
1120 C_LOGE("RDB: Error during finalizing statement: %s",
1121 sqlite3_errmsg(p_db));
1126 int revoke_app_permissions_internal(sqlite3 *p_db,
1127 const char *const s_app_label_name)
1129 RDB_LOG_ENTRY_PARAM("%s", s_app_label_name);
1131 int ret = PC_ERR_DB_OPERATION;
1132 sqlite3_stmt *p_stmt = NULL;
1134 ret = prepare_stmt(p_db, &p_stmt,
1135 "DELETE FROM app_permission_view \
1136 WHERE app_permission_view.app_name=%Q;",
1139 if(ret != PC_OPERATION_SUCCESS) goto finish;
1141 ret = step_and_convert_returned_value(p_stmt);
1143 if(sqlite3_finalize(p_stmt) < 0)
1144 C_LOGE("RDB: Error during finalizing statement: %s",
1145 sqlite3_errmsg(p_db));
1150 int reset_app_permissions_internal(sqlite3 *p_db,
1151 const char *const s_app_label_name)
1153 RDB_LOG_ENTRY_PARAM("%s", s_app_label_name);
1155 int ret = PC_ERR_DB_OPERATION;
1156 sqlite3_stmt *p_stmt = NULL;
1158 ret = prepare_stmt(p_db, &p_stmt,
1159 "DELETE FROM app_permission_volatile_view \
1160 WHERE app_permission_volatile_view.app_name=%Q;",
1163 if(ret != PC_OPERATION_SUCCESS) goto finish;
1165 ret = step_and_convert_returned_value(p_stmt);
1167 if(sqlite3_finalize(p_stmt) < 0)
1168 C_LOGE("RDB: Error during finalizing statement: %s",
1169 sqlite3_errmsg(p_db));
1174 int save_smack_rules(sqlite3 *p_db)
1178 if(sqlite3_exec(p_db,
1179 "DELETE FROM history_smack_rule; \
1181 INSERT INTO history_smack_rule \
1182 SELECT subject, object, access \
1183 FROM all_smack_binary_rules; \
1185 CREATE INDEX history_smack_rule_subject_object_index \
1186 ON history_smack_rule(subject, object);",
1187 0, 0, 0) != SQLITE_OK) {
1188 C_LOGE("RDB: Error during saving history table: %s",
1189 sqlite3_errmsg(p_db));
1190 return PC_ERR_DB_OPERATION;
1193 return PC_OPERATION_SUCCESS;
1197 int update_rules_in_db(sqlite3 *p_db)
1201 // All rules generated by the present state of the database
1202 if(sqlite3_exec(p_db,
1203 "DELETE FROM all_smack_binary_rules; \
1205 INSERT INTO all_smack_binary_rules \
1206 SELECT subject, object, access, is_volatile \
1207 FROM all_smack_binary_rules_view; \
1209 DELETE FROM all_smack_binary_rule_modified; \
1211 INSERT INTO all_smack_binary_rule_modified \
1212 SELECT subject, object, access \
1213 FROM all_smack_binary_rules, \
1215 WHERE subject IN modified_label OR \
1216 object IN modified_label; \
1218 DELETE FROM history_smack_rule_modified; \
1220 INSERT INTO history_smack_rule_modified \
1221 SELECT subject, object, access \
1222 FROM history_smack_rule, \
1224 WHERE subject IN modified_label OR \
1225 object IN modified_label; \
1227 0, 0, 0) != SQLITE_OK) {
1228 C_LOGE("RDB: Error during updating rules: %s",
1229 sqlite3_errmsg(p_db));
1230 return PC_ERR_DB_OPERATION;
1232 return PC_OPERATION_SUCCESS;
1235 int update_smack_rules(sqlite3 *p_db)
1239 int ret = PC_OPERATION_SUCCESS;
1240 sqlite3_stmt *p_stmt = NULL;
1241 const unsigned char *s_subject = NULL;
1242 const unsigned char *s_object = NULL;
1243 const unsigned char *s_access_add = NULL;
1244 const unsigned char *s_access_del = NULL;
1245 struct smack_accesses *smack = NULL;
1247 if(smack_accesses_new(&smack)) {
1248 C_LOGE("RDB: Error during updating smack rules: smack_accesses_new failed.");
1249 ret = PC_ERR_MEM_OPERATION;
1253 ret = prepare_stmt(p_db, &p_stmt,
1254 "SELECT * from modified_smack_rules;");
1255 if(ret != PC_OPERATION_SUCCESS) goto finish;
1257 while((ret = sqlite3_step(p_stmt)) == SQLITE_ROW) {
1258 s_subject = sqlite3_column_text(p_stmt, RDB_FIRST_COLUMN);
1259 s_object = sqlite3_column_text(p_stmt, RDB_SECOND_COLUMN);
1260 s_access_add = sqlite3_column_text(p_stmt, RDB_THIRD_COLUMN);
1261 s_access_del = sqlite3_column_text(p_stmt, RDB_FOURTH_COLUMN);
1263 C_LOGD("RDB: Added rule to smack:: %s %s %s %s",
1264 s_subject, s_object, s_access_add, s_access_del);
1266 if(smack_accesses_add_modify(smack,
1267 (const char *) s_subject,
1268 (const char *) s_object,
1269 (const char *) s_access_add,
1270 (const char *) s_access_del)) {
1271 C_LOGE("RDB: Error during updating smack rules: %s",
1272 sqlite3_errmsg(p_db));
1273 ret = PC_ERR_INVALID_OPERATION;
1277 if(ret == SQLITE_DONE) {
1278 ret = PC_OPERATION_SUCCESS;
1280 C_LOGE("RDB: Error during updating smack rules [%d]: %s",
1281 ret, sqlite3_errmsg(p_db));
1282 ret = PC_ERR_DB_OPERATION;
1285 if(smack_accesses_apply(smack)) {
1286 C_LOGE("RDB: Error in smack_accesses_apply");
1287 ret = PC_ERR_INVALID_OPERATION;
1291 if(sqlite3_finalize(p_stmt) < 0)
1292 C_LOGE("RDB: Error during finalizing statement: %s",
1293 sqlite3_errmsg(p_db));
1295 smack_accesses_free(smack);