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; \
216 CREATE TEMPORARY TABLE modified_label( \
217 name VARCHAR NOT NULL PRIMARY KEY); \
219 CREATE TEMPORARY TABLE all_smack_binary_rules_modified( \
220 subject TEXT NOT NULL, \
221 object TEXT NOT NULL, \
222 access INTEGER NOT NULL, \
223 is_volatile INTEGER NOT NULL); \
225 CREATE TEMPORARY TABLE current_smack_rule_modified( \
226 subject VARCHAR NOT NULL, \
227 object VARCHAR NOT NULL, \
228 access INTEGER NOT NULL); \
230 CREATE TEMPORARY TABLE history_smack_rule_modified( \
231 subject VARCHAR NOT NULL, \
232 object VARCHAR NOT NULL, \
233 access INTEGER NOT NULL); \
235 CREATE TEMPORARY VIEW modified_smack_rules AS \
236 SELECT subject, object, \
237 access_to_str(access_add) AS access_add, \
238 access_to_str(access_del) AS access_del \
240 SELECT subject, object, \
241 s1.access & ~s2.access AS access_add, \
242 s2.access & ~s1.access AS access_del \
243 FROM current_smack_rule_modified AS s1 \
244 INNER JOIN history_smack_rule_modified AS s2 \
245 USING (subject, object) \
246 WHERE s1.access != s2.access \
248 SELECT subject, object, \
249 s1.access AS access_add, \
251 FROM current_smack_rule_modified s1 \
252 LEFT JOIN history_smack_rule_modified s2 \
253 USING (subject, object) \
254 WHERE s2.subject IS NULL AND \
257 SELECT subject, object, \
259 s1.access AS access_del \
260 FROM history_smack_rule_modified s1 \
261 LEFT JOIN current_smack_rule_modified s2 \
262 USING (subject, object) \
263 WHERE s2.subject IS NULL AND \
266 ORDER BY subject, object ASC;",
267 0, 0, 0) != SQLITE_OK) {
268 C_LOGE("RDB: Error during preparing script: %s", sqlite3_errmsg(*p_db));
269 return PC_ERR_DB_OPERATION;
272 return PC_OPERATION_SUCCESS;
276 int prepare_stmt(sqlite3 *p_db,
277 sqlite3_stmt **pp_stmt,
278 const char *const s_sql,
281 int ret = PC_ERR_DB_QUERY_PREP;
282 char *s_query = NULL;
284 va_start(args, s_sql);
286 s_query = sqlite3_vmprintf(s_sql, args);
288 if(s_query == NULL) {
289 C_LOGE("RDB: Error during preparing statement: Unable to allocate enough memory.");
290 ret = PC_ERR_DB_QUERY_PREP;
294 if(sqlite3_prepare_v2(p_db,
299 C_LOGE("RDB: Error during preparing statement: %s", sqlite3_errmsg(p_db));
300 ret = PC_ERR_DB_QUERY_PREP;
304 if(*pp_stmt == NULL) {
305 C_LOGE("RDB: Error during preparing statement: SQL statement is probably empty.");
306 ret = PC_ERR_DB_QUERY_PREP;
310 ret = PC_OPERATION_SUCCESS;
314 sqlite3_free(s_query);
319 int check_app_label_internal(sqlite3 *p_db,
320 const char *const s_label_name)
322 RDB_LOG_ENTRY_PARAM("%s", s_label_name);
324 int ret = PC_ERR_DB_OPERATION;
325 sqlite3_stmt *p_stmt = NULL;
327 ret = prepare_stmt(p_db, &p_stmt,
329 FROM application_view \
330 WHERE application_view.name=%Q \
333 if(ret != PC_OPERATION_SUCCESS) goto finish;
335 ret = sqlite3_step(p_stmt);
336 if(ret == SQLITE_ROW) {
337 // There is such application label
338 ret = PC_ERR_DB_LABEL_TAKEN;
339 } else if(ret == SQLITE_DONE) {
340 // No such application label
341 ret = PC_OPERATION_SUCCESS;
343 C_LOGE("RDB: Error during stepping: %s", sqlite3_errmsg(p_db));
344 ret = PC_ERR_DB_QUERY_STEP;
347 if(sqlite3_finalize(p_stmt) < 0)
348 C_LOGE("RDB: Error during finalizing statement: %s",
349 sqlite3_errmsg(p_db));
354 int add_app_internal(sqlite3 *p_db,
355 const char *const s_label_name)
357 RDB_LOG_ENTRY_PARAM("%s", s_label_name);
359 int ret = PC_ERR_DB_OPERATION;
360 sqlite3_stmt *p_stmt = NULL;
362 ret = prepare_stmt(p_db, &p_stmt,
363 "INSERT into application_view(name) VALUES(%Q)",
365 if(ret != PC_OPERATION_SUCCESS) goto finish;
367 ret = step_and_convert_returned_value(p_stmt);
369 if(sqlite3_finalize(p_stmt) < 0)
370 C_LOGE("RDB: Error during finalizing statement: %s",
371 sqlite3_errmsg(p_db));
376 int remove_app_internal(sqlite3 *p_db,
377 const char *const s_label_name)
379 RDB_LOG_ENTRY_PARAM("%s", s_label_name);
381 int ret = PC_ERR_DB_OPERATION;
382 sqlite3_stmt *p_stmt = NULL;
384 ret = prepare_stmt(p_db, &p_stmt,
385 "DELETE FROM application_view \
386 WHERE application_view.name=%Q",
389 if(ret != PC_OPERATION_SUCCESS) goto finish;
391 ret = step_and_convert_returned_value(p_stmt);
393 if(sqlite3_finalize(p_stmt) < 0)
394 C_LOGE("RDB: Error during finalizing statement: %s",
395 sqlite3_errmsg(p_db));
400 int add_path_internal(sqlite3 *p_db,
401 const char *const s_owner_label_name,
402 const char *const s_path_label_name,
403 const char *const s_path,
404 const char *const s_access,
405 const char *const s_access_reverse,
406 const char *const s_type)
408 RDB_LOG_ENTRY_PARAM("%s %s %s %s %s %s",
409 s_owner_label_name, s_path_label_name,
410 s_path, s_access, s_access_reverse, s_type);
412 int ret = PC_ERR_DB_OPERATION;
413 sqlite3_stmt *p_stmt = NULL;
415 ret = prepare_stmt(p_db, &p_stmt,
416 "INSERT INTO path_view(owner_app_label_name, \
422 VALUES(%Q, %Q, %Q, %Q, %Q, %Q);",
423 s_owner_label_name, s_path, s_path_label_name,
424 s_access, s_access_reverse, s_type);
425 if(ret != PC_OPERATION_SUCCESS) goto finish;
427 ret = step_and_convert_returned_value(p_stmt);
429 if(sqlite3_finalize(p_stmt) < 0)
430 C_LOGE("RDB: Error during finalizing statement: %s",
431 sqlite3_errmsg(p_db));
436 int add_permission_internal(sqlite3 *p_db,
437 const char *const s_permission_name,
438 const char *const s_permission_type_name)
440 RDB_LOG_ENTRY_PARAM("%s %s", s_permission_name, s_permission_type_name);
442 int ret = PC_ERR_DB_OPERATION;
443 sqlite3_stmt *p_stmt = NULL;
445 ret = prepare_stmt(p_db, &p_stmt,
446 "INSERT INTO permission_view(name, type_name) \
448 s_permission_name, s_permission_type_name);
450 if(ret != PC_OPERATION_SUCCESS) goto finish;
452 ret = step_and_convert_returned_value(p_stmt);
454 if(sqlite3_finalize(p_stmt) < 0)
455 C_LOGE("RDB: Error during finalizing statement: %s",
456 sqlite3_errmsg(p_db));
461 int get_permission_id_internal(sqlite3 *p_db,
462 const char *const s_permission_name,
463 const char *const s_permission_type_name,
464 sqlite3_int64 *p_permission_id)
466 RDB_LOG_ENTRY_PARAM("%s %s", s_permission_name, s_permission_type_name);
468 int ret = PC_ERR_DB_OPERATION;
469 sqlite3_stmt *p_stmt = NULL;
471 ret = prepare_stmt(p_db, &p_stmt,
472 "SELECT permission_view.permission_id \
473 FROM permission_view \
474 WHERE permission_view.name = %Q AND \
475 permission_view.type_name = %Q \
477 s_permission_name, s_permission_type_name);
478 if(ret != PC_OPERATION_SUCCESS) goto finish;
480 ret = sqlite3_step(p_stmt);
481 if(ret == SQLITE_ROW) {
482 ret = PC_OPERATION_SUCCESS;
483 *p_permission_id = sqlite3_column_int(p_stmt, RDB_FIRST_COLUMN);
484 } else if(ret == SQLITE_DONE) {
485 C_LOGW("RDB: There is no permission_id for %s %s", s_permission_name, s_permission_type_name);
486 ret = PC_ERR_DB_OPERATION;
489 C_LOGE("RDB: Error during stepping: %s", sqlite3_errmsg(p_db));
490 ret = PC_ERR_DB_QUERY_STEP;
494 if(sqlite3_finalize(p_stmt) < 0)
495 C_LOGE("RDB: Error during finalizing statement: %s",
496 sqlite3_errmsg(p_db));
502 int prepare_stmts_for_bind(sqlite3 *p_db,
503 sqlite3_stmt **pp_stmt,
504 const char *const s_query)
506 if(sqlite3_prepare_v2(p_db,
511 C_LOGE("RDB: Error during preparing statement: %s",
512 sqlite3_errmsg(p_db));
513 return PC_ERR_DB_QUERY_PREP;
515 return PC_OPERATION_SUCCESS;
519 static int add_permission_label_rule(sqlite3_stmt *p_stmt,
520 const sqlite3_int64 i_permission_id,
521 const char *const s_label_name,
522 const char *const s_access,
523 const int i_is_reverse)
525 int ret = PC_OPERATION_SUCCESS;
527 // Bind values to the statement and run it:
528 // Bind returns SQLITE_OK == 0 on success
529 if(sqlite3_bind_int(p_stmt, 1, i_permission_id) ||
530 sqlite3_bind_text(p_stmt, 2, s_access, RDB_AUTO_DETERM_SIZE, 0) ||
531 sqlite3_bind_text(p_stmt, 3, s_label_name, RDB_AUTO_DETERM_SIZE, 0) ||
532 sqlite3_bind_int(p_stmt, 4, i_is_reverse)) {
533 C_LOGE("RDB: Error during binding to statement: %s",
534 sqlite3_errmsg(sqlite3_db_handle(p_stmt)));
535 ret = PC_ERR_DB_QUERY_BIND;
539 // Perform the insert
540 ret = step_and_convert_returned_value(p_stmt);
543 reset_and_unbind_stmt(p_stmt);
548 static int add_permission_permission_rule(sqlite3_stmt *p_stmt,
549 const sqlite3_int64 i_permission_id,
550 const sqlite3_int64 i_target_permission_id,
551 const char *const s_access,
552 const int i_is_reverse)
554 int ret = PC_OPERATION_SUCCESS;
556 if(sqlite3_bind_int(p_stmt, 1, i_permission_id) ||
557 sqlite3_bind_int(p_stmt, 2, i_target_permission_id) ||
558 sqlite3_bind_text(p_stmt, 3, s_access, RDB_AUTO_DETERM_SIZE, 0) ||
559 sqlite3_bind_int(p_stmt, 4, i_is_reverse)) {
560 C_LOGE("RDB: Error during binding to statement: %s",
561 sqlite3_errmsg(sqlite3_db_handle(p_stmt)));
562 ret = PC_ERR_DB_QUERY_BIND;
566 ret = step_and_convert_returned_value(p_stmt);
569 reset_and_unbind_stmt(p_stmt);
574 static int add_permission_app_path_type_rule(sqlite3_stmt *p_stmt,
575 const sqlite3_int64 i_permission_id,
576 const char *const s_path_type_name,
577 const char *const s_access,
578 const int i_is_reverse)
580 int ret = PC_OPERATION_SUCCESS;
582 if(sqlite3_bind_int(p_stmt, 1, i_permission_id) ||
583 sqlite3_bind_text(p_stmt, 2, s_path_type_name, RDB_AUTO_DETERM_SIZE, 0) ||
584 sqlite3_bind_text(p_stmt, 3, s_access, RDB_AUTO_DETERM_SIZE, 0) ||
585 sqlite3_bind_int(p_stmt, 4, i_is_reverse)) {
586 C_LOGE("RDB: Error during binding to statement: %s",
587 sqlite3_errmsg(sqlite3_db_handle(p_stmt)));
588 ret = PC_ERR_DB_QUERY_BIND;
592 ret = step_and_convert_returned_value(p_stmt);
595 reset_and_unbind_stmt(p_stmt);
599 int add_permission_rules_internal(sqlite3 *p_db,
600 const sqlite3_int64 i_permission_id,
601 const char *const *const pp_smack_rules)
605 int ret = PC_OPERATION_SUCCESS;
606 char s_label[SMACK_LABEL_LEN + 1];
607 char s_access[ACC_LEN + 1];
608 sqlite3_int64 i_all_apps_permission_id = 1;
609 int i_is_reverse = 0;
611 sqlite3_stmt *p_perm_to_label_stmt = NULL;
612 sqlite3_stmt *p_perm_to_perm_stmt = NULL;
613 sqlite3_stmt *p_perm_to_app_path_type_stmt = NULL;
615 // Prepare stmts. They are static, so we parse SQL only once per process and reuse it.
616 ret = prepare_stmts_for_bind(p_db, &p_perm_to_label_stmt,
617 "INSERT INTO permission_label_rule_view( \
618 permission_id, access, label_name, is_reverse) \
620 if(ret != PC_OPERATION_SUCCESS) goto finish;
622 ret = prepare_stmts_for_bind(p_db, &p_perm_to_perm_stmt,
623 "INSERT OR REPLACE INTO permission_permission_rule( \
624 permission_id, target_permission_id, \
625 access, is_reverse) \
626 VALUES(?,?,str_to_access(?),?)");
627 if(ret != PC_OPERATION_SUCCESS) goto finish;
630 ret = prepare_stmts_for_bind(p_db, &p_perm_to_app_path_type_stmt,
631 "INSERT INTO permission_app_path_type_rule_view( \
632 permission_id, app_path_type_name, access, is_reverse) \
634 if(ret != PC_OPERATION_SUCCESS) goto finish;
637 for(i = 0; pp_smack_rules[i] != NULL ; ++i) {
638 C_LOGD("RDB: Granting permission: %s", pp_smack_rules[i]);
640 // Ignore empty lines
641 if(strspn(pp_smack_rules[i], " \t\n") == strlen(pp_smack_rules[i]))
644 ret = parse_rule(pp_smack_rules[i], s_label, s_access, &i_is_reverse);
645 if(ret != PC_OPERATION_SUCCESS) goto finish;
647 // Interpret wildcards
648 if(s_label[0] != '~' &&
649 s_label[strlen(s_label) - 1] != '~') {
650 // It's not a wildcard!
651 ret = add_permission_label_rule(p_perm_to_label_stmt,
656 if(ret != PC_OPERATION_SUCCESS) goto finish;
658 } else if(!strcmp(s_label, "~ALL_APPS~")) {
659 ret = get_permission_id_internal(p_db,
662 &i_all_apps_permission_id);
663 if(ret != PC_OPERATION_SUCCESS) goto finish;
665 ret = add_permission_permission_rule(p_perm_to_perm_stmt,
667 i_all_apps_permission_id,
670 if(ret != PC_OPERATION_SUCCESS) goto finish;
672 } else if(!strcmp(s_label, "~ALL_APPS_WITH_SAME_PERMISSION~")) {
673 ret = add_permission_permission_rule(p_perm_to_perm_stmt,
678 if(ret != PC_OPERATION_SUCCESS) goto finish;
680 } else if(!strcmp(s_label, "~PUBLIC_PATH~")) {
681 ret = add_permission_app_path_type_rule(p_perm_to_app_path_type_stmt,
686 if(ret != PC_OPERATION_SUCCESS) goto finish;
688 } else if(!strcmp(s_label, "~GROUP_PATH~")) {
689 ret = add_permission_app_path_type_rule(p_perm_to_app_path_type_stmt,
694 if(ret != PC_OPERATION_SUCCESS) goto finish;
696 } else if(!strcmp(s_label, "~SETTINGS_PATH~")) {
697 ret = add_permission_app_path_type_rule(p_perm_to_app_path_type_stmt,
702 if(ret != PC_OPERATION_SUCCESS) goto finish;
706 ret = PC_OPERATION_SUCCESS;
709 if(p_perm_to_label_stmt &&
710 sqlite3_finalize(p_perm_to_label_stmt) < 0) {
711 C_LOGE("RDB: Error during finalizing statement: %s",
712 sqlite3_errmsg(p_db));
715 if(p_perm_to_perm_stmt &&
716 sqlite3_finalize(p_perm_to_perm_stmt) < 0) {
717 C_LOGE("RDB: Error during finalizing statement: %s",
718 sqlite3_errmsg(p_db));
721 if(p_perm_to_app_path_type_stmt &&
722 sqlite3_finalize(p_perm_to_app_path_type_stmt) < 0) {
723 C_LOGE("RDB: Error during finalizing statement: %s",
724 sqlite3_errmsg(p_db));
729 static int add_label_app_path_type_rule(sqlite3_stmt *p_stmt,
730 const char *const s_label_name,
731 const char *const s_path_type_name,
732 const char *const s_access,
733 const int i_is_reverse)
735 int ret = PC_OPERATION_SUCCESS;
737 if(sqlite3_bind_text(p_stmt, 1, s_label_name, RDB_AUTO_DETERM_SIZE, 0) ||
738 sqlite3_bind_text(p_stmt, 2, s_path_type_name, RDB_AUTO_DETERM_SIZE, 0) ||
739 sqlite3_bind_text(p_stmt, 3, s_access, RDB_AUTO_DETERM_SIZE, 0) ||
740 sqlite3_bind_int(p_stmt, 4, i_is_reverse)) {
741 C_LOGE("RDB: Error during binding to statement: %s",
742 sqlite3_errmsg(sqlite3_db_handle(p_stmt)));
743 ret = PC_ERR_DB_QUERY_BIND;
747 ret = step_and_convert_returned_value(p_stmt);
750 reset_and_unbind_stmt(p_stmt);
755 int add_additional_rules_internal(sqlite3 *p_db, const char *const *const pp_smack_rules)
758 int ret = PC_OPERATION_SUCCESS;
760 char s_subject[SMACK_LABEL_LEN + 1];
761 char s_object[SMACK_LABEL_LEN + 1];
762 char s_access[ACC_LEN + 1];
763 sqlite3_stmt *p_label_to_app_path_type_stmt = NULL;
765 char *ps_subject, *ps_object;
767 // Clear the label_app_path_type_rule table
768 if(sqlite3_exec(p_db, "DELETE FROM label_app_path_type_rule_view;", 0, 0, 0) != SQLITE_OK) {
769 C_LOGE("RDB: Error during clearing additional rules: %s", sqlite3_errmsg(p_db));
770 ret = PC_ERR_DB_OPERATION;
774 ret = prepare_stmts_for_bind(p_db, &p_label_to_app_path_type_stmt,
775 "INSERT INTO label_app_path_type_rule_view( \
776 label_name, app_path_type_name, access, is_reverse) \
778 if(ret != PC_OPERATION_SUCCESS) goto finish;
780 // Add rules to the database
781 for(i = 0; pp_smack_rules[i] != NULL ; ++i) {
783 // Ignore empty lines
784 if(strspn(pp_smack_rules[i], " \t\n") == strlen(pp_smack_rules[i]))
788 ret = tokenize_rule(pp_smack_rules[i], s_subject , s_object, s_access);
789 if(ret != PC_OPERATION_SUCCESS) goto finish;
791 if(is_wildcard(s_subject)) {
792 ps_subject = s_object;
793 ps_object = s_subject;
796 ps_subject = s_subject;
797 ps_object = s_object;
802 if(!smack_label_is_valid(ps_subject)) {
803 C_LOGE("Subject is not a valid label");
804 ret = PC_ERR_INVALID_PARAM;
808 // Add access to paths
809 if(!strcmp(ps_object, "~PUBLIC_PATH~")) {
810 ret = add_label_app_path_type_rule(p_label_to_app_path_type_stmt,
815 if(ret != PC_OPERATION_SUCCESS) goto finish;
817 } else if(!strcmp(ps_object, "~GROUP_PATH~")) {
818 ret = add_label_app_path_type_rule(p_label_to_app_path_type_stmt,
823 if(ret != PC_OPERATION_SUCCESS) goto finish;
825 } else if(!strcmp(ps_object, "~SETTINGS_PATH~")) {
826 ret = add_label_app_path_type_rule(p_label_to_app_path_type_stmt,
831 if(ret != PC_OPERATION_SUCCESS) goto finish;
832 } else if(!strcmp(ps_object, "~NPRUNTIME_PATH~")) {
833 ret = add_label_app_path_type_rule(p_label_to_app_path_type_stmt,
838 if(ret != PC_OPERATION_SUCCESS) goto finish;
842 // Mark label as modified
843 ret = add_modified_label_internal(p_db, ps_subject);
844 if(ret != PC_OPERATION_SUCCESS) goto finish;
848 if(p_label_to_app_path_type_stmt &&
849 sqlite3_finalize(p_label_to_app_path_type_stmt) < 0)
850 C_LOGE("RDB: Error during finalizing statement: %s",
851 sqlite3_errmsg(p_db));
855 int check_app_has_permission_internal(sqlite3 *p_db,
856 const char *const s_app_label_name,
857 const char *const s_permission_name,
858 const char *const s_permission_type_name,
859 bool *const p_is_enabled)
861 RDB_LOG_ENTRY_PARAM("%s %s %s", s_app_label_name,
862 s_permission_name, s_permission_type_name);
864 int ret = PC_ERR_DB_OPERATION;
865 sqlite3_stmt *p_stmt = NULL;
867 ret = prepare_stmt(p_db, &p_stmt,
869 FROM app_permission_view \
870 WHERE app_name = %Q AND \
874 s_app_label_name, s_permission_name, s_permission_type_name);
875 if(ret != PC_OPERATION_SUCCESS) goto finish;
877 ret = sqlite3_step(p_stmt);
878 if(ret == SQLITE_ROW) {
879 ret = PC_OPERATION_SUCCESS;
881 *p_is_enabled = (bool)sqlite3_column_int(p_stmt, RDB_FIRST_COLUMN);
882 } else if(ret == SQLITE_DONE) {
883 //no entry == permission not assigned
884 C_LOGD("RDB: Permission: %s of type: %s is not assigned to app: %s",
885 s_permission_name, s_permission_type_name, s_app_label_name);
886 ret = PC_OPERATION_SUCCESS;
887 *p_is_enabled = false;
888 } else if(ret == SQLITE_BUSY) {
889 //base locked in exclusive mode for too long
890 C_LOGE("RDB: Database is busy. RDB Connection Error returned.");
891 ret = PC_ERR_DB_CONNECTION;
893 C_LOGE("RDB: Error during stepping: %s", sqlite3_errmsg(p_db));
894 ret = PC_ERR_DB_QUERY_STEP;
898 if(sqlite3_finalize(p_stmt) < 0)
899 C_LOGE("RDB: Error during finalizing statement: %s",
900 sqlite3_errmsg(p_db));
904 int get_app_id_internal(sqlite3 *p_db,
906 const char *const s_app_label_name)
908 RDB_LOG_ENTRY_PARAM("%s", s_app_label_name);
910 int ret = PC_ERR_DB_OPERATION;
911 sqlite3_stmt *p_stmt = NULL;
913 ret = prepare_stmt(p_db, &p_stmt,
914 "SELECT application_view.app_id \
915 FROM application_view \
916 WHERE application_view.name = %Q",
919 if(ret != PC_OPERATION_SUCCESS) goto finish;
921 ret = sqlite3_step(p_stmt);
922 if(ret == SQLITE_ROW) {
923 ret = PC_OPERATION_SUCCESS;
924 *pi_app_id = sqlite3_column_int(p_stmt, RDB_FIRST_COLUMN);
926 } else if(ret == SQLITE_DONE) {
927 C_LOGW("RDB: There is no app_id for %s", s_app_label_name);
928 ret = PC_ERR_DB_OPERATION;
931 C_LOGE("RDB: Error during stepping: %s", sqlite3_errmsg(p_db));
932 ret = PC_ERR_DB_QUERY_STEP;
936 if(sqlite3_finalize(p_stmt) < 0)
937 C_LOGE("RDB: Error during finalizing statement: %s",
938 sqlite3_errmsg(p_db));
943 int add_app_permission_internal(sqlite3 *p_db,
945 const char *const s_permission_name,
946 const char *const s_permission_type_name,
947 const bool b_is_volatile_new,
948 const bool b_is_enabled_new)
950 RDB_LOG_ENTRY_PARAM("%d %s %s %d %d", i_app_id,
951 s_permission_name, s_permission_type_name,
952 b_is_volatile_new, b_is_enabled_new);
955 int ret = PC_ERR_DB_OPERATION;
956 sqlite3_stmt *p_stmt = NULL;
958 ret = prepare_stmt(p_db, &p_stmt,
960 app_permission_view(app_id, name, type_name, \
961 is_volatile, is_enabled) \
962 VALUES(%d,%Q,%Q,%d,%d)",
963 i_app_id, s_permission_name, s_permission_type_name,
964 (int)b_is_volatile_new, (int)b_is_enabled_new);
966 if(ret != PC_OPERATION_SUCCESS) goto finish;
968 ret = step_and_convert_returned_value(p_stmt);
970 if(sqlite3_finalize(p_stmt) < 0)
971 C_LOGE("RDB: Error during finalizing statement: %s",
972 sqlite3_errmsg(p_db));
977 int switch_app_permission_internal(sqlite3 *p_db,
979 const char *const s_permission_name,
980 const char *const s_permission_type_name,
981 const bool b_is_enabled_new)
983 RDB_LOG_ENTRY_PARAM("%d %s %s %d", i_app_id,
984 s_permission_name, s_permission_type_name,
987 int ret = PC_ERR_DB_OPERATION;
988 sqlite3_stmt *p_stmt = NULL;
990 ret = prepare_stmt(p_db, &p_stmt,
991 "UPDATE app_permission_view \
993 WHERE app_id = %d AND \
996 b_is_enabled_new, i_app_id,
997 s_permission_name, s_permission_type_name);
999 if(ret != PC_OPERATION_SUCCESS) goto finish;
1000 ret = step_and_convert_returned_value(p_stmt);
1002 if(sqlite3_finalize(p_stmt) < 0)
1003 C_LOGE("RDB: Error during finalizing statement: %s",
1004 sqlite3_errmsg(p_db));
1009 int update_app_permission_internal(sqlite3 *p_db,
1011 const int i_permission_id,
1012 const bool b_is_volatile_new,
1013 const bool b_is_enabled_new)
1015 RDB_LOG_ENTRY_PARAM("%d %d %d %d",
1016 i_app_id, i_permission_id,
1017 b_is_volatile_new, b_is_enabled_new);
1019 int ret = PC_ERR_DB_OPERATION;
1020 sqlite3_stmt *p_stmt = NULL;
1022 ret = prepare_stmt(p_db, &p_stmt,
1023 "UPDATE app_permission \
1024 SET is_volatile = %d, is_enabled=%d \
1025 WHERE app_id = %d AND permission_id = %d",
1026 b_is_volatile_new, b_is_enabled_new,
1027 i_app_id, i_permission_id);
1029 if(ret != PC_OPERATION_SUCCESS) goto finish;
1030 ret = step_and_convert_returned_value(p_stmt);
1032 if(sqlite3_finalize(p_stmt) < 0)
1033 C_LOGE("RDB: Error during finalizing statement: %s",
1034 sqlite3_errmsg(p_db));
1039 int change_app_permission_internal(sqlite3 *p_db,
1041 const char *const s_permission_name,
1042 const char *const s_permission_type_name,
1043 int i_is_volatile_new,
1044 int i_is_enabled_new)
1046 RDB_LOG_ENTRY_PARAM("%d %s %s %d %d", i_app_id,
1047 s_permission_name, s_permission_type_name,
1048 i_is_volatile_new, i_is_enabled_new);
1050 int ret = PC_ERR_DB_OPERATION;
1051 sqlite3_stmt *p_stmt = NULL;
1052 int i_is_volatile_old, i_is_enabled_old, i_permission_id;
1054 ret = prepare_stmt(p_db, &p_stmt,
1055 "SELECT is_volatile, is_enabled, permission_id \
1056 FROM app_permission_list_view \
1057 WHERE app_id = %d AND \
1058 permission_name=%Q AND \
1059 permission_type_name=%Q LIMIT 1",
1060 i_app_id, s_permission_name, s_permission_type_name);
1061 if(ret != PC_OPERATION_SUCCESS) goto finish;
1063 ret = sqlite3_step(p_stmt);
1064 if(ret == SQLITE_ROW) {
1065 // Phi, I already have this permission...
1066 i_is_volatile_old = sqlite3_column_int(p_stmt, RDB_FIRST_COLUMN);
1067 i_is_enabled_old = sqlite3_column_int(p_stmt, RDB_SECOND_COLUMN);
1069 if(i_is_volatile_old == 1 && i_is_volatile_new == 0) {
1070 // Confucius say, No man can down-cast volatility.
1071 C_LOGE("RDB: Down-casting volatility is forbidden.");
1072 ret = PC_ERR_DB_PERM_FORBIDDEN;
1076 if(i_is_volatile_old == i_is_volatile_new &&
1077 i_is_enabled_old == i_is_enabled_new) {
1078 // There is no change. Nice.
1079 C_LOGD("RDB: Permission %s %s already exists.", s_permission_name, s_permission_type_name);
1080 ret = PC_OPERATION_SUCCESS;
1084 i_permission_id = sqlite3_column_int(p_stmt, RDB_THIRD_COLUMN);
1086 // Finalize statement
1087 if(sqlite3_finalize(p_stmt) < 0)
1088 C_LOGE("RDB: Error during finalizing statement: %s",
1089 sqlite3_errmsg(p_db));
1092 C_LOGD("RDB: Updating permission %s %s to application.", s_permission_name, s_permission_type_name);
1093 ret = update_app_permission_internal(p_db,
1099 } else if(ret == SQLITE_DONE) {
1100 // Wow! A brand new permission! Omnomnom...
1102 if(sqlite3_finalize(p_stmt) < 0)
1103 C_LOGE("RDB: Error during finalizing statement: %s",
1104 sqlite3_errmsg(p_db));
1107 C_LOGD("RDB: Adding permission %s %s to application.", s_permission_name, s_permission_type_name);
1108 ret = add_app_permission_internal(p_db,
1111 s_permission_type_name,
1115 C_LOGE("RDB: Error during stepping: %s", sqlite3_errmsg(p_db));
1116 ret = PC_ERR_DB_QUERY_STEP;
1120 if(p_stmt && sqlite3_finalize(p_stmt) < 0)
1121 C_LOGE("RDB: Error during finalizing statement: %s",
1122 sqlite3_errmsg(p_db));
1127 int revoke_app_permissions_internal(sqlite3 *p_db,
1128 const char *const s_app_label_name)
1130 RDB_LOG_ENTRY_PARAM("%s", s_app_label_name);
1132 int ret = PC_ERR_DB_OPERATION;
1133 sqlite3_stmt *p_stmt = NULL;
1135 ret = prepare_stmt(p_db, &p_stmt,
1136 "DELETE FROM app_permission_view \
1137 WHERE app_permission_view.app_name=%Q;",
1140 if(ret != PC_OPERATION_SUCCESS) goto finish;
1142 ret = step_and_convert_returned_value(p_stmt);
1144 if(sqlite3_finalize(p_stmt) < 0)
1145 C_LOGE("RDB: Error during finalizing statement: %s",
1146 sqlite3_errmsg(p_db));
1151 int reset_app_permissions_internal(sqlite3 *p_db,
1152 const char *const s_app_label_name)
1154 RDB_LOG_ENTRY_PARAM("%s", s_app_label_name);
1156 int ret = PC_ERR_DB_OPERATION;
1157 sqlite3_stmt *p_stmt = NULL;
1159 ret = prepare_stmt(p_db, &p_stmt,
1160 "DELETE FROM app_permission_volatile_view \
1161 WHERE app_permission_volatile_view.app_name=%Q;",
1164 if(ret != PC_OPERATION_SUCCESS) goto finish;
1166 ret = step_and_convert_returned_value(p_stmt);
1168 if(sqlite3_finalize(p_stmt) < 0)
1169 C_LOGE("RDB: Error during finalizing statement: %s",
1170 sqlite3_errmsg(p_db));
1174 int update_rules_in_db(sqlite3 *p_db)
1178 if(sqlite3_exec(p_db,
1180 -- clean temporary tables\n \
1181 DELETE FROM all_smack_binary_rules_modified; \
1182 DELETE FROM current_smack_rule_modified; \
1183 DELETE FROM history_smack_rule_modified; \
1185 -- gather possibly modified rules\n \
1186 INSERT INTO all_smack_binary_rules_modified \
1187 SELECT subject, object, access, is_volatile \
1188 FROM all_smack_binary_rules_view \
1189 WHERE subject IN modified_label; \
1191 INSERT INTO all_smack_binary_rules_modified \
1192 SELECT subject, object, access, is_volatile \
1193 FROM all_smack_binary_rules_view \
1194 WHERE object IN modified_label AND subject NOT IN modified_label; \
1196 -- prepare aggregated rules for diff algorithm\n \
1197 INSERT INTO current_smack_rule_modified \
1198 SELECT subject, object, bitwise_or(access) \
1199 FROM all_smack_binary_rules_modified \
1200 GROUP BY subject, object \
1201 ORDER BY subject, object ASC; \
1203 INSERT INTO history_smack_rule_modified \
1204 SELECT subject, object, bitwise_or(access) \
1205 FROM all_smack_binary_rules \
1206 WHERE subject IN modified_label OR object IN modified_label \
1207 GROUP BY subject, object \
1208 ORDER BY subject, object ASC; \
1210 -- apply changes to all_smack_binary_rules\n \
1211 DELETE FROM all_smack_binary_rules \
1212 WHERE subject IN modified_label OR \
1213 object IN modified_label; \
1215 INSERT INTO all_smack_binary_rules \
1216 SELECT subject, object, access, is_volatile \
1217 FROM all_smack_binary_rules_modified; \
1220 DELETE FROM modified_label; \
1222 0, 0, 0) != SQLITE_OK) {
1223 C_LOGE("RDB: Error during updating rules: %s",
1224 sqlite3_errmsg(p_db));
1225 return PC_ERR_DB_OPERATION;
1227 return PC_OPERATION_SUCCESS;
1230 int update_smack_rules(sqlite3 *p_db)
1234 int ret = PC_OPERATION_SUCCESS;
1235 sqlite3_stmt *p_stmt = NULL;
1236 const unsigned char *s_subject = NULL;
1237 const unsigned char *s_object = NULL;
1238 const unsigned char *s_access_add = NULL;
1239 const unsigned char *s_access_del = NULL;
1240 struct smack_accesses *smack = NULL;
1242 if(smack_accesses_new(&smack)) {
1243 C_LOGE("RDB: Error during updating smack rules: smack_accesses_new failed.");
1244 ret = PC_ERR_MEM_OPERATION;
1248 ret = prepare_stmt(p_db, &p_stmt,
1249 "SELECT * from modified_smack_rules;");
1250 if(ret != PC_OPERATION_SUCCESS) goto finish;
1252 while((ret = sqlite3_step(p_stmt)) == SQLITE_ROW) {
1253 s_subject = sqlite3_column_text(p_stmt, RDB_FIRST_COLUMN);
1254 s_object = sqlite3_column_text(p_stmt, RDB_SECOND_COLUMN);
1255 s_access_add = sqlite3_column_text(p_stmt, RDB_THIRD_COLUMN);
1256 s_access_del = sqlite3_column_text(p_stmt, RDB_FOURTH_COLUMN);
1258 C_LOGD("RDB: Added rule to smack:: %s %s %s %s",
1259 s_subject, s_object, s_access_add, s_access_del);
1261 if(smack_accesses_add_modify(smack,
1262 (const char *) s_subject,
1263 (const char *) s_object,
1264 (const char *) s_access_add,
1265 (const char *) s_access_del)) {
1266 C_LOGE("RDB: Error during updating smack rules: %s",
1267 sqlite3_errmsg(p_db));
1268 ret = PC_ERR_INVALID_OPERATION;
1272 if(ret == SQLITE_DONE) {
1273 ret = PC_OPERATION_SUCCESS;
1275 C_LOGE("RDB: Error during updating smack rules [%d]: %s",
1276 ret, sqlite3_errmsg(p_db));
1277 ret = PC_ERR_DB_OPERATION;
1280 if(smack_accesses_apply(smack)) {
1281 C_LOGE("RDB: Error in smack_accesses_apply");
1282 ret = PC_ERR_INVALID_OPERATION;
1286 if(sqlite3_finalize(p_stmt) < 0)
1287 C_LOGE("RDB: Error during finalizing statement: %s",
1288 sqlite3_errmsg(p_db));
1290 smack_accesses_free(smack);